thingsboard-aplcache
Changes
application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java 39(+39 -0)
application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java 4(+4 -0)
application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java 34(+34 -0)
application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java 6(+5 -1)
common/data/src/main/java/org/thingsboard/server/common/data/entityview/EntityViewSearchQuery.java 1(+1 -0)
ui/src/app/api/entity.service.js 33(+33 -0)
ui/src/app/common/types.constant.js 8(+8 -0)
ui/src/app/entity/entity-filter.tpl.html 83(+83 -0)
ui/src/app/locale/locale.constant-es_ES.json 2104(+1171 -933)
ui/src/app/widget/lib/google-map.js 2(+1 -1)
Details
diff --git a/application/src/main/data/upgrade/2.1.2/schema_update.cql b/application/src/main/data/upgrade/2.1.2/schema_update.cql
new file mode 100644
index 0000000..c02571a
--- /dev/null
+++ b/application/src/main/data/upgrade/2.1.2/schema_update.cql
@@ -0,0 +1,110 @@
+--
+-- Copyright © 2016-2018 The Thingsboard Authors
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+
+DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_name;
+DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_search_text;
+DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_customer;
+DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_entity_id;
+
+DROP TABLE IF EXISTS thingsboard.entity_views;
+
+CREATE TABLE IF NOT EXISTS thingsboard.entity_view (
+ id timeuuid,
+ entity_id timeuuid,
+ entity_type text,
+ tenant_id timeuuid,
+ customer_id timeuuid,
+ name text,
+ type text,
+ keys text,
+ start_ts bigint,
+ end_ts bigint,
+ search_text text,
+ additional_info text,
+ PRIMARY KEY (id, entity_id, tenant_id, customer_id, type)
+);
+
+CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_name AS
+ SELECT *
+ from thingsboard.entity_view
+ WHERE tenant_id IS NOT NULL
+ AND entity_id IS NOT NULL
+ AND customer_id IS NOT NULL
+ AND type IS NOT NULL
+ AND name IS NOT NULL
+ AND id IS NOT NULL
+ PRIMARY KEY (tenant_id, name, id, customer_id, entity_id, type)
+ WITH CLUSTERING ORDER BY (name ASC, id DESC, customer_id DESC);
+
+CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_search_text AS
+ SELECT *
+ from thingsboard.entity_view
+ WHERE tenant_id IS NOT NULL
+ AND entity_id IS NOT NULL
+ AND customer_id IS NOT NULL
+ AND type IS NOT NULL
+ AND search_text IS NOT NULL
+ AND id IS NOT NULL
+ PRIMARY KEY (tenant_id, search_text, id, customer_id, entity_id, type)
+ WITH CLUSTERING ORDER BY (search_text ASC, id DESC, customer_id DESC);
+
+CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_by_type_and_search_text AS
+ SELECT *
+ from thingsboard.entity_view
+ WHERE tenant_id IS NOT NULL
+ AND entity_id IS NOT NULL
+ AND customer_id IS NOT NULL
+ AND type IS NOT NULL
+ AND search_text IS NOT NULL
+ AND id IS NOT NULL
+ PRIMARY KEY (tenant_id, type, search_text, id, customer_id, entity_id)
+ WITH CLUSTERING ORDER BY (type ASC, search_text ASC, id DESC, customer_id DESC);
+
+CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_customer AS
+ SELECT *
+ from thingsboard.entity_view
+ WHERE tenant_id IS NOT NULL
+ AND customer_id IS NOT NULL
+ AND entity_id IS NOT NULL
+ AND type IS NOT NULL
+ AND search_text IS NOT NULL
+ AND id IS NOT NULL
+ PRIMARY KEY (tenant_id, customer_id, search_text, id, entity_id, type)
+ WITH CLUSTERING ORDER BY (customer_id DESC, search_text ASC, id DESC);
+
+CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_customer_and_type AS
+ SELECT *
+ from thingsboard.entity_view
+ WHERE tenant_id IS NOT NULL
+ AND customer_id IS NOT NULL
+ AND entity_id IS NOT NULL
+ AND type IS NOT NULL
+ AND search_text IS NOT NULL
+ AND id IS NOT NULL
+ PRIMARY KEY (tenant_id, type, customer_id, search_text, id, entity_id)
+ WITH CLUSTERING ORDER BY (type ASC, customer_id DESC, search_text ASC, id DESC);
+
+CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_entity_id AS
+ SELECT *
+ from thingsboard.entity_view
+ WHERE tenant_id IS NOT NULL
+ AND customer_id IS NOT NULL
+ AND entity_id IS NOT NULL
+ AND type IS NOT NULL
+ AND search_text IS NOT NULL
+ AND id IS NOT NULL
+ PRIMARY KEY (tenant_id, entity_id, customer_id, search_text, id, type)
+ WITH CLUSTERING ORDER BY (entity_id DESC, customer_id DESC, search_text ASC, id DESC);
\ No newline at end of file
diff --git a/application/src/main/data/upgrade/2.1.2/schema_update.sql b/application/src/main/data/upgrade/2.1.2/schema_update.sql
new file mode 100644
index 0000000..14b717c
--- /dev/null
+++ b/application/src/main/data/upgrade/2.1.2/schema_update.sql
@@ -0,0 +1,32 @@
+--
+-- Copyright © 2016-2018 The Thingsboard Authors
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+
+DROP TABLE IF EXISTS entity_views;
+
+CREATE TABLE IF NOT EXISTS entity_view (
+ id varchar(31) NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY,
+ entity_id varchar(31),
+ entity_type varchar(255),
+ tenant_id varchar(31),
+ customer_id varchar(31),
+ type varchar(255),
+ name varchar(255),
+ keys varchar(255),
+ start_ts bigint,
+ end_ts bigint,
+ search_text varchar(255),
+ additional_info varchar
+);
diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
index 0ba35e8..a1ba1c6 100644
--- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
@@ -15,6 +15,7 @@
*/
package org.thingsboard.server.controller;
+import com.google.common.util.concurrent.ListenableFuture;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
@@ -26,6 +27,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.Customer;
+import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.audit.ActionType;
@@ -38,6 +40,7 @@ import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants;
+import org.thingsboard.server.service.security.model.SecurityUser;
import java.util.List;
import java.util.stream.Collectors;
@@ -161,6 +164,7 @@ public class EntityViewController extends BaseController {
public TextPageData<EntityView> getCustomerEntityViews(
@PathVariable("customerId") String strCustomerId,
@RequestParam int limit,
+ @RequestParam(required = false) String type,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String idOffset,
@RequestParam(required = false) String textOffset) throws ThingsboardException {
@@ -170,7 +174,11 @@ public class EntityViewController extends BaseController {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
checkCustomerId(customerId);
TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
- return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
+ if (type != null && type.trim().length() > 0) {
+ return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerIdAndType(tenantId, customerId, pageLink, type));
+ } else {
+ return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
+ }
} catch (Exception e) {
throw handleException(e);
}
@@ -181,13 +189,19 @@ public class EntityViewController extends BaseController {
@ResponseBody
public TextPageData<EntityView> getTenantEntityViews(
@RequestParam int limit,
+ @RequestParam(required = false) String type,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String idOffset,
@RequestParam(required = false) String textOffset) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();
TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
- return checkNotNull(entityViewService.findEntityViewByTenantId(tenantId, pageLink));
+
+ if (type != null && type.trim().length() > 0) {
+ return checkNotNull(entityViewService.findEntityViewByTenantIdAndType(tenantId, pageLink, type));
+ } else {
+ return checkNotNull(entityViewService.findEntityViewByTenantId(tenantId, pageLink));
+ }
} catch (Exception e) {
throw handleException(e);
}
@@ -199,6 +213,7 @@ public class EntityViewController extends BaseController {
public List<EntityView> findByQuery(@RequestBody EntityViewSearchQuery query) throws ThingsboardException {
checkNotNull(query);
checkNotNull(query.getParameters());
+ checkNotNull(query.getEntityViewTypes());
checkEntityId(query.getParameters().getEntityId());
try {
List<EntityView> entityViews = checkNotNull(entityViewService.findEntityViewsByQuery(query).get());
@@ -215,4 +230,18 @@ public class EntityViewController extends BaseController {
throw handleException(e);
}
}
+
+ @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
+ @RequestMapping(value = "/entityView/types", method = RequestMethod.GET)
+ @ResponseBody
+ public List<EntitySubtype> getEntityViewTypes() throws ThingsboardException {
+ try {
+ SecurityUser user = getCurrentUser();
+ TenantId tenantId = user.getTenantId();
+ ListenableFuture<List<EntitySubtype>> entityViewTypes = entityViewService.findEntityViewTypesByTenantId(tenantId);
+ return checkNotNull(entityViewTypes.get());
+ } catch (Exception e) {
+ throw handleException(e);
+ }
+ }
}
diff --git a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
index da154e9..45eb66a 100644
--- a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
+++ b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
@@ -97,6 +97,11 @@ public class ThingsboardInstallService {
databaseUpgradeService.upgradeDatabase("2.0.0");
+ case "2.1.1":
+ log.info("Upgrading ThingsBoard from version 2.1.1 to 2.1.2 ...");
+
+ databaseUpgradeService.upgradeDatabase("2.1.1");
+
log.info("Updating system data...");
systemDataLoaderService.deleteSystemWidgetBundle("charts");
diff --git a/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java
index 934cf8d..5526953 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java
@@ -39,10 +39,19 @@ import static org.thingsboard.server.service.install.DatabaseHelper.CONFIGURATIO
import static org.thingsboard.server.service.install.DatabaseHelper.CUSTOMER_ID;
import static org.thingsboard.server.service.install.DatabaseHelper.DASHBOARD;
import static org.thingsboard.server.service.install.DatabaseHelper.DEVICE;
+import static org.thingsboard.server.service.install.DatabaseHelper.END_TS;
+import static org.thingsboard.server.service.install.DatabaseHelper.ENTITY_ID;
+import static org.thingsboard.server.service.install.DatabaseHelper.ENTITY_TYPE;
+import static org.thingsboard.server.service.install.DatabaseHelper.ENTITY_VIEW;
+import static org.thingsboard.server.service.install.DatabaseHelper.ENTITY_VIEWS;
import static org.thingsboard.server.service.install.DatabaseHelper.ID;
+import static org.thingsboard.server.service.install.DatabaseHelper.KEYS;
+import static org.thingsboard.server.service.install.DatabaseHelper.NAME;
import static org.thingsboard.server.service.install.DatabaseHelper.SEARCH_TEXT;
+import static org.thingsboard.server.service.install.DatabaseHelper.START_TS;
import static org.thingsboard.server.service.install.DatabaseHelper.TENANT_ID;
import static org.thingsboard.server.service.install.DatabaseHelper.TITLE;
+import static org.thingsboard.server.service.install.DatabaseHelper.TYPE;
@Service
@NoSqlDao
@@ -213,6 +222,36 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService {
break;
+ case "2.1.1":
+
+ log.info("Upgrading Cassandra DataBase from version {} to 2.1.2 ...", fromVersion);
+
+ cluster.getSession();
+
+ ks = cluster.getCluster().getMetadata().getKeyspace(cluster.getKeyspaceName());
+
+ log.info("Dumping entity views ...");
+ Path entityViewsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), ENTITY_VIEWS,
+ new String[]{ID, ENTITY_ID, ENTITY_TYPE, TENANT_ID, CUSTOMER_ID, NAME, TYPE, KEYS, START_TS, END_TS, SEARCH_TEXT, ADDITIONAL_INFO},
+ new String[]{"", "", "", "", "", "", "default", "", "0", "0", "", ""},
+ "tb-entity-views");
+ log.info("Entity views dumped.");
+
+ log.info("Updating schema ...");
+ schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.1.2", SCHEMA_UPDATE_CQL);
+ loadCql(schemaUpdateFile);
+ log.info("Schema updated.");
+
+ log.info("Restoring entity views ...");
+ if (entityViewsDump != null) {
+ CassandraDbHelper.loadCf(ks, cluster.getSession(), ENTITY_VIEW,
+ new String[]{ID, ENTITY_ID, ENTITY_TYPE, TENANT_ID, CUSTOMER_ID, NAME, TYPE, KEYS, START_TS, END_TS, SEARCH_TEXT, ADDITIONAL_INFO}, entityViewsDump);
+ Files.deleteIfExists(entityViewsDump);
+ }
+ log.info("Entity views restored.");
+
+ break;
+
default:
throw new RuntimeException("Unable to upgrade Cassandra database, unsupported fromVersion: " + fromVersion);
}
diff --git a/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java b/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java
index bdf980f..7c03a71 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java
@@ -147,6 +147,8 @@ public class CassandraDbHelper {
str = new Double(row.getDouble(index)).toString();
} else if (type == DataType.cint()) {
str = new Integer(row.getInt(index)).toString();
+ } else if (type == DataType.bigint()) {
+ str = new Long(row.getLong(index)).toString();
} else if (type == DataType.uuid()) {
str = row.getUUID(index).toString();
} else if (type == DataType.timeuuid()) {
@@ -193,6 +195,8 @@ public class CassandraDbHelper {
boundStatement.setDouble(column, Double.valueOf(value));
} else if (type == DataType.cint()) {
boundStatement.setInt(column, Integer.valueOf(value));
+ } else if (type == DataType.bigint()) {
+ boundStatement.setLong(column, Long.valueOf(value));
} else if (type == DataType.uuid()) {
boundStatement.setUUID(column, UUID.fromString(value));
} else if (type == DataType.timeuuid()) {
diff --git a/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java b/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java
index 2f9b4a5..699eaf1 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java
@@ -45,14 +45,23 @@ public class DatabaseHelper {
public static final CSVFormat CSV_DUMP_FORMAT = CSVFormat.DEFAULT.withNullString("\\N");
public static final String DEVICE = "device";
+ public static final String ENTITY_ID = "entity_id";
public static final String TENANT_ID = "tenant_id";
+ public static final String ENTITY_TYPE = "entity_type";
public static final String CUSTOMER_ID = "customer_id";
public static final String SEARCH_TEXT = "search_text";
public static final String ADDITIONAL_INFO = "additional_info";
public static final String ASSET = "asset";
public static final String DASHBOARD = "dashboard";
+ public static final String ENTITY_VIEWS = "entity_views";
+ public static final String ENTITY_VIEW = "entity_view";
public static final String ID = "id";
public static final String TITLE = "title";
+ public static final String TYPE = "type";
+ public static final String NAME = "name";
+ public static final String KEYS = "keys";
+ public static final String START_TS = "start_ts";
+ public static final String END_TS = "end_ts";
public static final String ASSIGNED_CUSTOMERS = "assigned_customers";
public static final String CONFIGURATION = "configuration";
diff --git a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
index 7d701b7..2c7f89c 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
@@ -31,14 +31,24 @@ import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.DriverManager;
+import static org.thingsboard.server.service.install.DatabaseHelper.ADDITIONAL_INFO;
import static org.thingsboard.server.service.install.DatabaseHelper.ASSIGNED_CUSTOMERS;
import static org.thingsboard.server.service.install.DatabaseHelper.CONFIGURATION;
import static org.thingsboard.server.service.install.DatabaseHelper.CUSTOMER_ID;
import static org.thingsboard.server.service.install.DatabaseHelper.DASHBOARD;
+import static org.thingsboard.server.service.install.DatabaseHelper.END_TS;
+import static org.thingsboard.server.service.install.DatabaseHelper.ENTITY_ID;
+import static org.thingsboard.server.service.install.DatabaseHelper.ENTITY_TYPE;
+import static org.thingsboard.server.service.install.DatabaseHelper.ENTITY_VIEW;
+import static org.thingsboard.server.service.install.DatabaseHelper.ENTITY_VIEWS;
import static org.thingsboard.server.service.install.DatabaseHelper.ID;
+import static org.thingsboard.server.service.install.DatabaseHelper.KEYS;
+import static org.thingsboard.server.service.install.DatabaseHelper.NAME;
import static org.thingsboard.server.service.install.DatabaseHelper.SEARCH_TEXT;
+import static org.thingsboard.server.service.install.DatabaseHelper.START_TS;
import static org.thingsboard.server.service.install.DatabaseHelper.TENANT_ID;
import static org.thingsboard.server.service.install.DatabaseHelper.TITLE;
+import static org.thingsboard.server.service.install.DatabaseHelper.TYPE;
@Service
@Profile("install")
@@ -115,6 +125,30 @@ public class SqlDatabaseUpgradeService implements DatabaseUpgradeService {
log.info("Schema updated.");
}
break;
+ case "2.1.1":
+ try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
+
+ log.info("Dumping entity views ...");
+ Path entityViewsDump = SqlDbHelper.dumpTableIfExists(conn, ENTITY_VIEWS,
+ new String[]{ID, ENTITY_ID, ENTITY_TYPE, TENANT_ID, CUSTOMER_ID, TYPE, NAME, KEYS, START_TS, END_TS, SEARCH_TEXT, ADDITIONAL_INFO},
+ new String[]{"", "", "", "", "", "default", "", "", "0", "0", "", ""},
+ "tb-entity-views", true);
+ log.info("Entity views dumped.");
+
+ log.info("Updating schema ...");
+ schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.1.2", SCHEMA_UPDATE_SQL);
+ loadSql(schemaUpdateFile, conn);
+ log.info("Schema updated.");
+
+ log.info("Restoring entity views ...");
+ if (entityViewsDump != null) {
+ SqlDbHelper.loadTable(conn, ENTITY_VIEW,
+ new String[]{ID, ENTITY_ID, ENTITY_TYPE, TENANT_ID, CUSTOMER_ID, TYPE, NAME, KEYS, START_TS, END_TS, SEARCH_TEXT, ADDITIONAL_INFO}, entityViewsDump, true);
+ Files.deleteIfExists(entityViewsDump);
+ }
+ log.info("Entity views restored.");
+ }
+ break;
default:
throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java
index ee97b97..cb45006 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java
@@ -144,7 +144,9 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes
@Test
public void testSaveEntityViewWithEmptyName() throws Exception {
- doPost("/api/entityView", new EntityView())
+ EntityView entityView = new EntityView();
+ entityView.setType("default");
+ doPost("/api/entityView", entityView)
.andExpect(status().isBadRequest())
.andExpect(statusReason(containsString("Entity view name should be specified!")));
}
@@ -355,6 +357,7 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes
view.setEntityId(testDevice.getId());
view.setTenantId(savedTenant.getId());
view.setName("Test entity view");
+ view.setType("default");
view.setKeys(telemetry);
view.setStartTimeMs((long) getValue(valueTelemetryOfDevices, "lastActivityTime") * 10);
view.setEndTimeMs((long) getValue(valueTelemetryOfDevices, "lastActivityTime") / 10);
@@ -402,6 +405,7 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes
view.setEntityId(testDevice.getId());
view.setTenantId(savedTenant.getId());
view.setName(name);
+ view.setType("default");
view.setKeys(telemetry);
return doPost("/api/entityView", view, EntityView.class);
}
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityView.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityView.java
index 25b066d..f684e2a 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityView.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityView.java
@@ -40,6 +40,7 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId>
private TenantId tenantId;
private CustomerId customerId;
private String name;
+ private String type;
private TelemetryEntityView keys;
private long startTimeMs;
private long endTimeMs;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/entityview/EntityViewSearchQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/entityview/EntityViewSearchQuery.java
index 752eafc..3bf08ea 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/entityview/EntityViewSearchQuery.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/entityview/EntityViewSearchQuery.java
@@ -30,6 +30,7 @@ public class EntityViewSearchQuery {
private RelationsSearchParameters parameters;
private String relationType;
+ private List<String> entityViewTypes;
public EntityRelationsQuery toEntitySearchQuery() {
EntityRelationsQuery query = new EntityRelationsQuery();
diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java
index a03dd89..fe1a8d1 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java
@@ -15,8 +15,13 @@
*/
package org.thingsboard.server.dao.entityview;
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.ResultSetFuture;
import com.datastax.driver.core.Statement;
import com.datastax.driver.core.querybuilder.Select;
+import com.datastax.driver.mapping.Result;
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -30,6 +35,8 @@ import org.thingsboard.server.dao.model.nosql.EntityViewEntity;
import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao;
import org.thingsboard.server.dao.util.NoSqlDao;
+import javax.annotation.Nullable;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -39,14 +46,21 @@ import java.util.UUID;
import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
import static org.thingsboard.server.dao.model.ModelConstants.CUSTOMER_ID_PROPERTY;
+import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_TYPE_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_ID_COLUMN;
+import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_SUBTYPE_COLUMN_FAMILY_NAME;
+import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY;
+import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_SUBTYPE_TENANT_ID_PROPERTY;
+import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_BY_TENANT_AND_CUSTOMER_AND_TYPE_CF;
import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_BY_TENANT_AND_CUSTOMER_CF;
import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_BY_TENANT_AND_ENTITY_ID_CF;
import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_BY_TENANT_AND_NAME;
-import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME;
+import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_CF;
+import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_CF;
import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_NAME_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_TABLE_FAMILY_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_TENANT_ID_PROPERTY;
+import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_TYPE_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.TENANT_ID_PROPERTY;
/**
@@ -82,7 +96,7 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
public List<EntityView> findEntityViewsByTenantId(UUID tenantId, TextPageLink pageLink) {
log.debug("Try to find entity views by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
List<EntityViewEntity> entityViewEntities =
- findPageWithTextSearch(ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
+ findPageWithTextSearch(ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_CF,
Collections.singletonList(eq(TENANT_ID_PROPERTY, tenantId)), pageLink);
log.trace("Found entity views [{}] by tenantId [{}] and pageLink [{}]",
entityViewEntities, tenantId, pageLink);
@@ -90,6 +104,18 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
}
@Override
+ public List<EntityView> findEntityViewsByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink) {
+ log.debug("Try to find entity views by tenantId [{}], type [{}] and pageLink [{}]", tenantId, type, pageLink);
+ List<EntityViewEntity> entityViewEntities =
+ findPageWithTextSearch(ENTITY_VIEW_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_CF,
+ Arrays.asList(eq(ENTITY_VIEW_TYPE_PROPERTY, type),
+ eq(TENANT_ID_PROPERTY, tenantId)), pageLink);
+ log.trace("Found entity views [{}] by tenantId [{}], type [{}] and pageLink [{}]",
+ entityViewEntities, tenantId, type, pageLink);
+ return DaoUtil.convertDataList(entityViewEntities);
+ }
+
+ @Override
public Optional<EntityView> findEntityViewByTenantIdAndName(UUID tenantId, String name) {
Select.Where query = select().from(ENTITY_VIEW_BY_TENANT_AND_NAME).where();
query.and(eq(ENTITY_VIEW_TENANT_ID_PROPERTY, tenantId));
@@ -111,6 +137,19 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
}
@Override
+ public List<EntityView> findEntityViewsByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink) {
+ log.debug("Try to find entity views by tenantId [{}], customerId[{}], type [{}] and pageLink [{}]",
+ tenantId, customerId, type, pageLink);
+ List<EntityViewEntity> entityViewEntities = findPageWithTextSearch(
+ ENTITY_VIEW_BY_TENANT_AND_CUSTOMER_AND_TYPE_CF,
+ Arrays.asList(eq(DEVICE_TYPE_PROPERTY, type), eq(CUSTOMER_ID_PROPERTY, customerId), eq(TENANT_ID_PROPERTY, tenantId)),
+ pageLink);
+ log.trace("Found find entity views [{}] by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]",
+ entityViewEntities, tenantId, customerId, type, pageLink);
+ return DaoUtil.convertDataList(entityViewEntities);
+ }
+
+ @Override
public ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(UUID tenantId, UUID entityId) {
log.debug("Try to find entity views by tenantId [{}] and entityId [{}]", tenantId, entityId);
Select.Where query = select().from(ENTITY_VIEW_BY_TENANT_AND_ENTITY_ID_CF).where();
@@ -118,4 +157,30 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
query.and(eq(ENTITY_ID_COLUMN, entityId));
return findListByStatementAsync(query);
}
+
+ @Override
+ public ListenableFuture<List<EntitySubtype>> findTenantEntityViewTypesAsync(UUID tenantId) {
+ Select select = select().from(ENTITY_SUBTYPE_COLUMN_FAMILY_NAME);
+ Select.Where query = select.where();
+ query.and(eq(ENTITY_SUBTYPE_TENANT_ID_PROPERTY, tenantId));
+ query.and(eq(ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, EntityType.ENTITY_VIEW));
+ query.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
+ ResultSetFuture resultSetFuture = executeAsyncRead(query);
+ return Futures.transform(resultSetFuture, new Function<ResultSet, List<EntitySubtype>>() {
+ @Nullable
+ @Override
+ public List<EntitySubtype> apply(@Nullable ResultSet resultSet) {
+ Result<EntitySubtypeEntity> result = cluster.getMapper(EntitySubtypeEntity.class).map(resultSet);
+ if (result != null) {
+ List<EntitySubtype> entitySubtypes = new ArrayList<>();
+ result.all().forEach((entitySubtypeEntity) ->
+ entitySubtypes.add(entitySubtypeEntity.toEntitySubtype())
+ );
+ return entitySubtypes;
+ } else {
+ return Collections.emptyList();
+ }
+ }
+ });
+ }
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java
index ba43385..8147a07 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java
@@ -17,6 +17,7 @@ package org.thingsboard.server.dao.entityview;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.dao.Dao;
@@ -48,6 +49,16 @@ public interface EntityViewDao extends Dao<EntityView> {
List<EntityView> findEntityViewsByTenantId(UUID tenantId, TextPageLink pageLink);
/**
+ * Find entity views by tenantId, type and page link.
+ *
+ * @param tenantId the tenantId
+ * @param type the type
+ * @param pageLink the page link
+ * @return the list of entity view objects
+ */
+ List<EntityView> findEntityViewsByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink);
+
+ /**
* Find entity views by tenantId and entity view name.
*
* @param tenantId the tenantId
@@ -68,6 +79,27 @@ public interface EntityViewDao extends Dao<EntityView> {
UUID customerId,
TextPageLink pageLink);
+ /**
+ * Find entity views by tenantId, customerId, type and page link.
+ *
+ * @param tenantId the tenantId
+ * @param customerId the customerId
+ * @param type the type
+ * @param pageLink the page link
+ * @return the list of entity view objects
+ */
+ List<EntityView> findEntityViewsByTenantIdAndCustomerIdAndType(UUID tenantId,
+ UUID customerId,
+ String type,
+ TextPageLink pageLink);
ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(UUID tenantId, UUID entityId);
+
+ /**
+ * Find tenants entity view types.
+ *
+ * @return the list of tenant entity view type objects
+ */
+ ListenableFuture<List<EntitySubtype>> findTenantEntityViewTypesAsync(UUID tenantId);
+
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java
index 19f326c..da87b44 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java
@@ -16,6 +16,7 @@
package org.thingsboard.server.dao.entityview;
import com.google.common.util.concurrent.ListenableFuture;
+import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
import org.thingsboard.server.common.data.id.CustomerId;
@@ -44,8 +45,12 @@ public interface EntityViewService {
TextPageData<EntityView> findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink);
+ TextPageData<EntityView> findEntityViewByTenantIdAndType(TenantId tenantId, TextPageLink pageLink, String type);
+
TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink);
+ TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, TextPageLink pageLink, String type);
+
ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query);
ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId);
@@ -55,4 +60,6 @@ public interface EntityViewService {
void deleteEntityView(EntityViewId entityViewId);
void deleteEntityViewsByTenantId(TenantId tenantId);
+
+ ListenableFuture<List<EntitySubtype>> findEntityViewTypesByTenantId(TenantId tenantId);
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
index 2c5ec75..6b4ffbc 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
@@ -15,6 +15,7 @@
*/
package org.thingsboard.server.dao.entityview;
+import com.google.common.base.Function;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -29,6 +30,8 @@ import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.DataConstants;
+import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.Tenant;
@@ -54,6 +57,8 @@ import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
@@ -63,6 +68,7 @@ import static org.thingsboard.server.common.data.CacheConstants.RELATIONS_CACHE;
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
import static org.thingsboard.server.dao.service.Validator.validateId;
import static org.thingsboard.server.dao.service.Validator.validatePageLink;
+import static org.thingsboard.server.dao.service.Validator.validateString;
/**
* Created by Victor Basanets on 8/28/2017.
@@ -158,6 +164,16 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
}
@Override
+ public TextPageData<EntityView> findEntityViewByTenantIdAndType(TenantId tenantId, TextPageLink pageLink, String type) {
+ log.trace("Executing findEntityViewByTenantIdAndType, tenantId [{}], pageLink [{}], type [{}]", tenantId, pageLink, type);
+ validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
+ validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink);
+ validateString(type, "Incorrect type " + type);
+ List<EntityView> entityViews = entityViewDao.findEntityViewsByTenantIdAndType(tenantId.getId(), type, pageLink);
+ return new TextPageData<>(entityViews, pageLink);
+ }
+
+ @Override
public TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId,
TextPageLink pageLink) {
log.trace("Executing findEntityViewByTenantIdAndCustomerId, tenantId [{}], customerId [{}]," +
@@ -171,6 +187,19 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
}
@Override
+ public TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, TextPageLink pageLink, String type) {
+ log.trace("Executing findEntityViewsByTenantIdAndCustomerIdAndType, tenantId [{}], customerId [{}]," +
+ " pageLink [{}], type [{}]", tenantId, customerId, pageLink, type);
+ validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
+ validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
+ validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink);
+ validateString(type, "Incorrect type " + type);
+ List<EntityView> entityViews = entityViewDao.findEntityViewsByTenantIdAndCustomerIdAndType(tenantId.getId(),
+ customerId.getId(), type, pageLink);
+ return new TextPageData<>(entityViews, pageLink);
+ }
+
+ @Override
public ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query) {
ListenableFuture<List<EntityRelation>> relations = relationService.findByQuery(query.toEntitySearchQuery());
ListenableFuture<List<EntityView>> entityViews = Futures.transformAsync(relations, r -> {
@@ -184,6 +213,15 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
}
return Futures.successfulAsList(futures);
});
+
+ entityViews = Futures.transform(entityViews, new Function<List<EntityView>, List<EntityView>>() {
+ @Nullable
+ @Override
+ public List<EntityView> apply(@Nullable List<EntityView> entityViewList) {
+ return entityViewList == null ? Collections.emptyList() : entityViewList.stream().filter(entityView -> query.getEntityViewTypes().contains(entityView.getType())).collect(Collectors.toList());
+ }
+ });
+
return entityViews;
}
@@ -216,6 +254,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
public void onSuccess(@Nullable List<EntityView> result) {
cache.putIfAbsent(tenantIdAndEntityId, result);
}
+
@Override
public void onFailure(Throwable t) {
log.error("Error while finding entity views by tenantId and entityId", t);
@@ -243,6 +282,18 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
tenantEntityViewRemover.removeEntities(tenantId);
}
+ @Override
+ public ListenableFuture<List<EntitySubtype>> findEntityViewTypesByTenantId(TenantId tenantId) {
+ log.trace("Executing findEntityViewTypesByTenantId, tenantId [{}]", tenantId);
+ validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
+ ListenableFuture<List<EntitySubtype>> tenantEntityViewTypes = entityViewDao.findTenantEntityViewTypesAsync(tenantId.getId());
+ return Futures.transform(tenantEntityViewTypes,
+ entityViewTypes -> {
+ entityViewTypes.sort(Comparator.comparing(EntitySubtype::getType));
+ return entityViewTypes;
+ });
+ }
+
private ListenableFuture<List<Void>> copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection<String> keys) {
if (keys != null && !keys.isEmpty()) {
ListenableFuture<List<AttributeKvEntry>> getAttrFuture = attributesService.find(entityView.getEntityId(), scope, keys);
@@ -296,6 +347,9 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
@Override
protected void validateDataImpl(EntityView entityView) {
+ if (StringUtils.isEmpty(entityView.getType())) {
+ throw new DataValidationException("Entity View type should be specified!");
+ }
if (StringUtils.isEmpty(entityView.getName())) {
throw new DataValidationException("Entity view name should be specified!");
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
index a487ede..86ba594 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
@@ -145,18 +145,21 @@ public class ModelConstants {
/**
* Cassandra entityView constants.
*/
- public static final String ENTITY_VIEW_TABLE_FAMILY_NAME = "entity_views";
+ public static final String ENTITY_VIEW_TABLE_FAMILY_NAME = "entity_view";
public static final String ENTITY_VIEW_ENTITY_ID_PROPERTY = ENTITY_ID_COLUMN;
public static final String ENTITY_VIEW_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
public static final String ENTITY_VIEW_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY;
public static final String ENTITY_VIEW_NAME_PROPERTY = DEVICE_NAME_PROPERTY;
public static final String ENTITY_VIEW_BY_TENANT_AND_CUSTOMER_CF = "entity_view_by_tenant_and_customer";
+ public static final String ENTITY_VIEW_BY_TENANT_AND_CUSTOMER_AND_TYPE_CF = "entity_view_by_tenant_and_customer_and_type";
public static final String ENTITY_VIEW_BY_TENANT_AND_ENTITY_ID_CF = "entity_view_by_tenant_and_entity_id";
public static final String ENTITY_VIEW_KEYS_PROPERTY = "keys";
+ public static final String ENTITY_VIEW_TYPE_PROPERTY = "type";
public static final String ENTITY_VIEW_START_TS_PROPERTY = "start_ts";
public static final String ENTITY_VIEW_END_TS_PROPERTY = "end_ts";
public static final String ENTITY_VIEW_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
- public static final String ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "entity_view_by_tenant_and_search_text";
+ public static final String ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_CF = "entity_view_by_tenant_and_search_text";
+ public static final String ENTITY_VIEW_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_CF = "entity_view_by_tenant_by_type_and_search_text";
public static final String ENTITY_VIEW_BY_TENANT_AND_NAME = "entity_view_by_tenant_and_name";
/**
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EntityViewEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EntityViewEntity.java
index eb7f4fe..cda4217 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EntityViewEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EntityViewEntity.java
@@ -41,6 +41,7 @@ import javax.persistence.Enumerated;
import java.io.IOException;
import java.util.UUID;
+import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_TYPE_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_TYPE_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_VIEW_TABLE_FAMILY_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY;
@@ -71,6 +72,10 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
@Column(name = ModelConstants.ENTITY_VIEW_CUSTOMER_ID_PROPERTY)
private UUID customerId;
+ @PartitionKey(value = 3)
+ @Column(name = DEVICE_TYPE_PROPERTY)
+ private String type;
+
@Column(name = ModelConstants.ENTITY_VIEW_ENTITY_ID_PROPERTY)
private UUID entityId;
@@ -113,6 +118,7 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
if (entityView.getCustomerId() != null) {
this.customerId = entityView.getCustomerId().getId();
}
+ this.type = entityView.getType();
this.name = entityView.getName();
try {
this.keys = mapper.writeValueAsString(entityView.getKeys());
@@ -143,6 +149,7 @@ public class EntityViewEntity implements SearchTextEntity<EntityView> {
if (customerId != null) {
entityView.setCustomerId(new CustomerId(customerId));
}
+ entityView.setType(type);
entityView.setName(name);
try {
entityView.setKeys(mapper.readValue(keys, TelemetryEntityView.class));
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityViewEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityViewEntity.java
index 60f6951..6999c0c 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityViewEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityViewEntity.java
@@ -69,6 +69,9 @@ public class EntityViewEntity extends BaseSqlEntity<EntityView> implements Searc
@Column(name = ModelConstants.ENTITY_VIEW_CUSTOMER_ID_PROPERTY)
private String customerId;
+ @Column(name = ModelConstants.DEVICE_TYPE_PROPERTY)
+ private String type;
+
@Column(name = ModelConstants.ENTITY_VIEW_NAME_PROPERTY)
private String name;
@@ -108,6 +111,7 @@ public class EntityViewEntity extends BaseSqlEntity<EntityView> implements Searc
if (entityView.getCustomerId() != null) {
this.customerId = toString(entityView.getCustomerId().getId());
}
+ this.type = entityView.getType();
this.name = entityView.getName();
try {
this.keys = mapper.writeValueAsString(entityView.getKeys());
@@ -144,6 +148,7 @@ public class EntityViewEntity extends BaseSqlEntity<EntityView> implements Searc
if (customerId != null) {
entityView.setCustomerId(new CustomerId(toUUID(customerId)));
}
+ entityView.setType(type);
entityView.setName(name);
try {
entityView.setKeys(mapper.readValue(keys, TelemetryEntityView.class));
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java
index 0f5fdf5..efd1bd9 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java
@@ -19,8 +19,6 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
-import org.thingsboard.server.common.data.EntityView;
-import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.dao.model.sql.EntityViewEntity;
import org.thingsboard.server.dao.util.SqlDao;
@@ -36,21 +34,46 @@ public interface EntityViewRepository extends CrudRepository<EntityViewEntity, S
"AND LOWER(e.searchText) LIKE LOWER(CONCAT(:textSearch, '%')) " +
"AND e.id > :idOffset ORDER BY e.id")
List<EntityViewEntity> findByTenantId(@Param("tenantId") String tenantId,
- @Param("textSearch") String textSearch,
- @Param("idOffset") String idOffset,
- Pageable pageable);
+ @Param("textSearch") String textSearch,
+ @Param("idOffset") String idOffset,
+ Pageable pageable);
+
+ @Query("SELECT e FROM EntityViewEntity e WHERE e.tenantId = :tenantId " +
+ "AND e.type = :type " +
+ "AND LOWER(e.searchText) LIKE LOWER(CONCAT(:textSearch, '%')) " +
+ "AND e.id > :idOffset ORDER BY e.id")
+ List<EntityViewEntity> findByTenantIdAndType(@Param("tenantId") String tenantId,
+ @Param("type") String type,
+ @Param("textSearch") String textSearch,
+ @Param("idOffset") String idOffset,
+ Pageable pageable);
@Query("SELECT e FROM EntityViewEntity e WHERE e.tenantId = :tenantId " +
"AND e.customerId = :customerId " +
"AND LOWER(e.searchText) LIKE LOWER(CONCAT(:searchText, '%')) " +
"AND e.id > :idOffset ORDER BY e.id")
List<EntityViewEntity> findByTenantIdAndCustomerId(@Param("tenantId") String tenantId,
- @Param("customerId") String customerId,
- @Param("searchText") String searchText,
- @Param("idOffset") String idOffset,
- Pageable pageable);
+ @Param("customerId") String customerId,
+ @Param("searchText") String searchText,
+ @Param("idOffset") String idOffset,
+ Pageable pageable);
+
+ @Query("SELECT e FROM EntityViewEntity e WHERE e.tenantId = :tenantId " +
+ "AND e.customerId = :customerId " +
+ "AND e.type = :type " +
+ "AND LOWER(e.searchText) LIKE LOWER(CONCAT(:searchText, '%')) " +
+ "AND e.id > :idOffset ORDER BY e.id")
+ List<EntityViewEntity> findByTenantIdAndCustomerIdAndType(@Param("tenantId") String tenantId,
+ @Param("customerId") String customerId,
+ @Param("type") String type,
+ @Param("searchText") String searchText,
+ @Param("idOffset") String idOffset,
+ Pageable pageable);
EntityViewEntity findByTenantIdAndName(String tenantId, String name);
List<EntityViewEntity> findAllByTenantIdAndEntityId(String tenantId, String entityId);
+
+ @Query("SELECT DISTINCT ev.type FROM EntityViewEntity ev WHERE ev.tenantId = :tenantId")
+ List<String> findTenantEntityViewTypes(@Param("tenantId") String tenantId);
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java
index 912c9d5..1ba9b9e 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java
@@ -24,7 +24,6 @@ import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.UUIDConverter;
-import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.dao.DaoUtil;
@@ -41,7 +40,6 @@ import java.util.Optional;
import java.util.UUID;
import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID;
-import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUIDs;
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID_STR;
/**
@@ -76,6 +74,17 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao<EntityViewEntity,
}
@Override
+ public List<EntityView> findEntityViewsByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink) {
+ return DaoUtil.convertDataList(
+ entityViewRepository.findByTenantIdAndType(
+ fromTimeUUID(tenantId),
+ type,
+ Objects.toString(pageLink.getTextSearch(), ""),
+ pageLink.getIdOffset() == null ? NULL_UUID_STR : fromTimeUUID(pageLink.getIdOffset()),
+ new PageRequest(0, pageLink.getLimit())));
+ }
+
+ @Override
public Optional<EntityView> findEntityViewByTenantIdAndName(UUID tenantId, String name) {
return Optional.ofNullable(
DaoUtil.getData(entityViewRepository.findByTenantIdAndName(fromTimeUUID(tenantId), name)));
@@ -96,8 +105,37 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao<EntityViewEntity,
}
@Override
+ public List<EntityView> findEntityViewsByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink) {
+ return DaoUtil.convertDataList(
+ entityViewRepository.findByTenantIdAndCustomerIdAndType(
+ fromTimeUUID(tenantId),
+ fromTimeUUID(customerId),
+ type,
+ Objects.toString(pageLink.getTextSearch(), ""),
+ pageLink.getIdOffset() == null ? NULL_UUID_STR : fromTimeUUID(pageLink.getIdOffset()),
+ new PageRequest(0, pageLink.getLimit())
+ ));
+ }
+
+ @Override
public ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(UUID tenantId, UUID entityId) {
return service.submit(() -> DaoUtil.convertDataList(
entityViewRepository.findAllByTenantIdAndEntityId(UUIDConverter.fromTimeUUID(tenantId), UUIDConverter.fromTimeUUID(entityId))));
}
+
+ @Override
+ public ListenableFuture<List<EntitySubtype>> findTenantEntityViewTypesAsync(UUID tenantId) {
+ return service.submit(() -> convertTenantEntityViewTypesToDto(tenantId, entityViewRepository.findTenantEntityViewTypes(fromTimeUUID(tenantId))));
+ }
+
+ private List<EntitySubtype> convertTenantEntityViewTypesToDto(UUID tenantId, List<String> types) {
+ List<EntitySubtype> list = Collections.emptyList();
+ if (types != null && !types.isEmpty()) {
+ list = new ArrayList<>();
+ for (String type : types) {
+ list.add(new EntitySubtype(new TenantId(tenantId), EntityType.ENTITY_VIEW, type));
+ }
+ }
+ return list;
+ }
}
diff --git a/dao/src/main/resources/cassandra/schema-entities.cql b/dao/src/main/resources/cassandra/schema-entities.cql
index 7ccd41f..ef27c70 100644
--- a/dao/src/main/resources/cassandra/schema-entities.cql
+++ b/dao/src/main/resources/cassandra/schema-entities.cql
@@ -624,61 +624,90 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_node (
PRIMARY KEY (id)
);
-CREATE TABLE IF NOT EXISTS thingsboard.entity_views (
+CREATE TABLE IF NOT EXISTS thingsboard.entity_view (
id timeuuid,
entity_id timeuuid,
entity_type text,
tenant_id timeuuid,
customer_id timeuuid,
name text,
+ type text,
keys text,
start_ts bigint,
end_ts bigint,
search_text text,
additional_info text,
- PRIMARY KEY (id, entity_id, tenant_id, customer_id)
+ PRIMARY KEY (id, entity_id, tenant_id, customer_id, type)
);
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_name AS
SELECT *
- from thingsboard.entity_views
+ from thingsboard.entity_view
WHERE tenant_id IS NOT NULL
AND entity_id IS NOT NULL
AND customer_id IS NOT NULL
+ AND type IS NOT NULL
AND name IS NOT NULL
AND id IS NOT NULL
- PRIMARY KEY (tenant_id, name, id, customer_id, entity_id)
+ PRIMARY KEY (tenant_id, name, id, customer_id, entity_id, type)
WITH CLUSTERING ORDER BY (name ASC, id DESC, customer_id DESC);
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_search_text AS
SELECT *
- from thingsboard.entity_views
+ from thingsboard.entity_view
WHERE tenant_id IS NOT NULL
AND entity_id IS NOT NULL
AND customer_id IS NOT NULL
+ AND type IS NOT NULL
AND search_text IS NOT NULL
AND id IS NOT NULL
- PRIMARY KEY (tenant_id, search_text, id, customer_id, entity_id)
+ PRIMARY KEY (tenant_id, search_text, id, customer_id, entity_id, type)
WITH CLUSTERING ORDER BY (search_text ASC, id DESC, customer_id DESC);
+CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_by_type_and_search_text AS
+ SELECT *
+ from thingsboard.entity_view
+ WHERE tenant_id IS NOT NULL
+ AND entity_id IS NOT NULL
+ AND customer_id IS NOT NULL
+ AND type IS NOT NULL
+ AND search_text IS NOT NULL
+ AND id IS NOT NULL
+ PRIMARY KEY (tenant_id, type, search_text, id, customer_id, entity_id)
+ WITH CLUSTERING ORDER BY (type ASC, search_text ASC, id DESC, customer_id DESC);
+
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_customer AS
SELECT *
- from thingsboard.entity_views
+ from thingsboard.entity_view
WHERE tenant_id IS NOT NULL
AND customer_id IS NOT NULL
AND entity_id IS NOT NULL
+ AND type IS NOT NULL
AND search_text IS NOT NULL
AND id IS NOT NULL
- PRIMARY KEY (tenant_id, customer_id, search_text, id, entity_id)
+ PRIMARY KEY (tenant_id, customer_id, search_text, id, entity_id, type)
WITH CLUSTERING ORDER BY (customer_id DESC, search_text ASC, id DESC);
+CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_customer_and_type AS
+ SELECT *
+ from thingsboard.entity_view
+ WHERE tenant_id IS NOT NULL
+ AND customer_id IS NOT NULL
+ AND entity_id IS NOT NULL
+ AND type IS NOT NULL
+ AND search_text IS NOT NULL
+ AND id IS NOT NULL
+ PRIMARY KEY (tenant_id, type, customer_id, search_text, id, entity_id)
+ WITH CLUSTERING ORDER BY (type ASC, customer_id DESC, search_text ASC, id DESC);
+
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_entity_id AS
SELECT *
- from thingsboard.entity_views
+ from thingsboard.entity_view
WHERE tenant_id IS NOT NULL
AND customer_id IS NOT NULL
AND entity_id IS NOT NULL
+ AND type IS NOT NULL
AND search_text IS NOT NULL
AND id IS NOT NULL
- PRIMARY KEY (tenant_id, entity_id, customer_id, search_text, id)
+ PRIMARY KEY (tenant_id, entity_id, customer_id, search_text, id, type)
WITH CLUSTERING ORDER BY (entity_id DESC, customer_id DESC, search_text ASC, id DESC);
\ No newline at end of file
diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql
index abd20ab..0b9c853 100644
--- a/dao/src/main/resources/sql/schema-entities.sql
+++ b/dao/src/main/resources/sql/schema-entities.sql
@@ -228,12 +228,13 @@ CREATE TABLE IF NOT EXISTS rule_node (
search_text varchar(255)
);
-CREATE TABLE IF NOT EXISTS entity_views (
+CREATE TABLE IF NOT EXISTS entity_view (
id varchar(31) NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY,
entity_id varchar(31),
entity_type varchar(255),
tenant_id varchar(31),
customer_id varchar(31),
+ type varchar(255),
name varchar(255),
keys varchar(255),
start_ts bigint,
diff --git a/dao/src/test/resources/sql/drop-all-tables.sql b/dao/src/test/resources/sql/drop-all-tables.sql
index b1fb72c..1bdc1a7 100644
--- a/dao/src/test/resources/sql/drop-all-tables.sql
+++ b/dao/src/test/resources/sql/drop-all-tables.sql
@@ -19,4 +19,4 @@ DROP TABLE IF EXISTS widget_type;
DROP TABLE IF EXISTS widgets_bundle;
DROP TABLE IF EXISTS rule_node;
DROP TABLE IF EXISTS rule_chain;
-DROP TABLE IF EXISTS entity_views;
+DROP TABLE IF EXISTS entity_view;
ui/src/app/api/entity.service.js 33(+33 -0)
diff --git a/ui/src/app/api/entity.service.js b/ui/src/app/api/entity.service.js
index ce4dc42..205abc9 100644
--- a/ui/src/app/api/entity.service.js
+++ b/ui/src/app/api/entity.service.js
@@ -533,6 +533,21 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
}
);
break;
+ case types.aliasFilterType.entityViewType.value:
+ getEntitiesByNameFilter(types.entityType.entityView, filter.entityViewNameFilter, maxItems, {ignoreLoading: true}, filter.entityViewType).then(
+ function success(entities) {
+ if (entities && entities.length || !failOnEmpty) {
+ result.entities = entitiesToEntitiesInfo(entities);
+ deferred.resolve(result);
+ } else {
+ deferred.reject();
+ }
+ },
+ function fail() {
+ deferred.reject();
+ }
+ );
+ break;
case types.aliasFilterType.relationsQuery.value:
result.stateEntity = filter.rootStateEntity;
var rootEntityType;
@@ -578,6 +593,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
break;
case types.aliasFilterType.assetSearchQuery.value:
case types.aliasFilterType.deviceSearchQuery.value:
+ case types.aliasFilterType.entityViewSearchQuery.value:
result.stateEntity = filter.rootStateEntity;
if (result.stateEntity && stateEntityId) {
rootEntityType = stateEntityId.entityType;
@@ -604,6 +620,9 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
} else if (filter.type == types.aliasFilterType.deviceSearchQuery.value) {
searchQuery.deviceTypes = filter.deviceTypes;
findByQueryPromise = deviceService.findByQuery(searchQuery, false, {ignoreLoading: true});
+ } else if (filter.type == types.aliasFilterType.entityViewSearchQuery.value) {
+ searchQuery.entityViewTypes = filter.entityViewTypes;
+ findByQueryPromise = entityViewService.findByQuery(searchQuery, false, {ignoreLoading: true});
}
findByQueryPromise.then(
function success(entities) {
@@ -646,6 +665,8 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
return entityTypes.indexOf(types.entityType.asset) > -1 ? true : false;
case types.aliasFilterType.deviceType.value:
return entityTypes.indexOf(types.entityType.device) > -1 ? true : false;
+ case types.aliasFilterType.entityViewType.value:
+ return entityTypes.indexOf(types.entityType.entityView) > -1 ? true : false;
case types.aliasFilterType.relationsQuery.value:
if (filter.filters && filter.filters.length) {
var match = false;
@@ -671,6 +692,8 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
return entityTypes.indexOf(types.entityType.asset) > -1 ? true : false;
case types.aliasFilterType.deviceSearchQuery.value:
return entityTypes.indexOf(types.entityType.device) > -1 ? true : false;
+ case types.aliasFilterType.entityViewSearchQuery.value:
+ return entityTypes.indexOf(types.entityType.entityView) > -1 ? true : false;
}
}
return false;
@@ -690,12 +713,16 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
return entityType === types.entityType.asset;
case types.aliasFilterType.deviceType.value:
return entityType === types.entityType.device;
+ case types.aliasFilterType.entityViewType.value:
+ return entityType === types.entityType.entityView;
case types.aliasFilterType.relationsQuery.value:
return true;
case types.aliasFilterType.assetSearchQuery.value:
return entityType === types.entityType.asset;
case types.aliasFilterType.deviceSearchQuery.value:
return entityType === types.entityType.device;
+ case types.aliasFilterType.entityViewSearchQuery.value:
+ return entityType === types.entityType.entityView;
}
return false;
}
@@ -1046,6 +1073,8 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
return assetService.deleteAsset(entityId.id);
} else if (entityId.entityType == types.entityType.device) {
return deviceService.deleteDevice(entityId.id);
+ } else if (entityId.entityType == types.entityType.entityView) {
+ return entityViewService.deleteEntityView(entityId.id);
}
}
@@ -1151,6 +1180,8 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
return assetService.saveAsset(entity);
} else if (entityType == types.entityType.device) {
return deviceService.saveDevice(entity);
+ } else if (entityType == types.entityType.entityView) {
+ return entityViewService.saveEntityView(entity);
}
}
@@ -1279,6 +1310,8 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
searchQuery.assetTypes = entitySubTypes;
} else if (entityType == types.entityType.device) {
searchQuery.deviceTypes = entitySubTypes;
+ } else if (entityType == types.entityType.entityView) {
+ searchQuery.entityViewTypes = entitySubTypes;
} else {
return null; //Not supported
}
ui/src/app/common/types.constant.js 8(+8 -0)
diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js
index 15da584..506ef1d 100644
--- a/ui/src/app/common/types.constant.js
+++ b/ui/src/app/common/types.constant.js
@@ -253,6 +253,10 @@ export default angular.module('thingsboard.types', [])
value: 'deviceType',
name: 'alias.filter-type-device-type'
},
+ entityViewType: {
+ value: 'entityViewType',
+ name: 'alias.filter-type-entity-view-type'
+ },
relationsQuery: {
value: 'relationsQuery',
name: 'alias.filter-type-relations-query'
@@ -264,6 +268,10 @@ export default angular.module('thingsboard.types', [])
deviceSearchQuery: {
value: 'deviceSearchQuery',
name: 'alias.filter-type-device-search-query'
+ },
+ entityViewSearchQuery: {
+ value: 'entityViewSearchQuery',
+ name: 'alias.filter-type-entity-view-search-query'
}
},
position: {
diff --git a/ui/src/app/entity/entity-filter.directive.js b/ui/src/app/entity/entity-filter.directive.js
index 0c8f646..38641fb 100644
--- a/ui/src/app/entity/entity-filter.directive.js
+++ b/ui/src/app/entity/entity-filter.directive.js
@@ -69,9 +69,14 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc
filter.deviceType = null;
filter.deviceNameFilter = '';
break;
+ case types.aliasFilterType.entityViewType.value:
+ filter.entityViewType = null;
+ filter.entityViewNameFilter = '';
+ break;
case types.aliasFilterType.relationsQuery.value:
case types.aliasFilterType.assetSearchQuery.value:
case types.aliasFilterType.deviceSearchQuery.value:
+ case types.aliasFilterType.entityViewSearchQuery.value:
filter.rootStateEntity = false;
filter.stateEntityParamName = null;
filter.defaultStateEntity = null;
@@ -86,6 +91,9 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc
} else if (filter.type === types.aliasFilterType.deviceSearchQuery.value) {
filter.relationType = null;
filter.deviceTypes = [];
+ } else if (filter.type === types.aliasFilterType.entityViewSearchQuery.value) {
+ filter.relationType = null;
+ filter.entityViewTypes = [];
}
break;
}
ui/src/app/entity/entity-filter.tpl.html 83(+83 -0)
diff --git a/ui/src/app/entity/entity-filter.tpl.html b/ui/src/app/entity/entity-filter.tpl.html
index f9aac3c..95193f2 100644
--- a/ui/src/app/entity/entity-filter.tpl.html
+++ b/ui/src/app/entity/entity-filter.tpl.html
@@ -112,6 +112,20 @@
aria-label="{{ 'device.name-starts-with' | translate }}">
</md-input-container>
</section>
+ <section layout="column" ng-if="filter.type == types.aliasFilterType.entityViewType.value" id="entityViewTypeFilter">
+ <tb-entity-subtype-autocomplete
+ tb-required="true"
+ the-form="theForm"
+ ng-model="filter.entityViewType"
+ entity-type="types.entityType.entityView">
+ </tb-entity-subtype-autocomplete>
+ <md-input-container class="md-block">
+ <label translate>entity-view.name-starts-with</label>
+ <input name="entityViewNameFilter"
+ ng-model="filter.entityViewNameFilter"
+ aria-label="{{ 'entity-view.name-starts-with' | translate }}">
+ </md-input-container>
+ </section>
<section layout="column" ng-if="filter.type == types.aliasFilterType.relationsQuery.value" id="relationsQueryFilter">
<label class="tb-small">{{ 'alias.root-entity' | translate }}</label>
<section class="tb-root-state-entity-switch" layout="row" layout-align="start center" style="padding-left: 0px;">
@@ -311,4 +325,73 @@
ng-model="filter.deviceTypes">
</tb-entity-subtype-list>
</section>
+ <section layout="column" ng-if="filter.type == types.aliasFilterType.entityViewSearchQuery.value" id="entityViewSearchQueryFilter">
+ <label class="tb-small">{{ 'alias.root-entity' | translate }}</label>
+ <section class="tb-root-state-entity-switch" layout="row" layout-align="start center" style="padding-left: 0px;">
+ <md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
+ aria-label="{{ 'alias.root-state-entity' | translate }}">
+ </md-switch>
+ <label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
+ </section>
+ <div flex layout="row" ng-if="!filter.rootStateEntity">
+ <tb-entity-select flex
+ the-form="theForm"
+ tb-required="!filter.rootStateEntity"
+ ng-disabled="filter.rootStateEntity"
+ use-alias-entity-types="true"
+ ng-model="filter.rootEntity">
+ </tb-entity-select>
+ </div>
+ <div flex layout="row" ng-if="filter.rootStateEntity">
+ <md-input-container class="md-block" style="margin-top: 32px;">
+ <label translate>alias.state-entity-parameter-name</label>
+ <input name="stateEntityParamName"
+ placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
+ ng-model="filter.stateEntityParamName"
+ aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
+ </md-input-container>
+ <div flex layout="column">
+ <label class="tb-small">{{ 'alias.default-state-entity' | translate }}</label>
+ <tb-entity-select flex
+ the-form="theForm"
+ tb-required="false"
+ use-alias-entity-types="true"
+ ng-model="filter.defaultStateEntity">
+ </tb-entity-select>
+ </div>
+ </div>
+ <div flex layout="row">
+ <md-input-container class="md-block" style="min-width: 100px;">
+ <label translate>relation.direction</label>
+ <md-select required ng-model="filter.direction">
+ <md-option ng-repeat="direction in types.entitySearchDirection" ng-value="direction">
+ {{ ('relation.search-direction.' + direction) | translate}}
+ </md-option>
+ </md-select>
+ </md-input-container>
+ <md-input-container flex class="md-block">
+ <label translate>alias.max-relation-level</label>
+ <input name="maxRelationLevel"
+ type="number"
+ min="1"
+ step="1"
+ placeholder="{{ 'alias.unlimited-level' | translate }}"
+ ng-model="filter.maxLevel"
+ aria-label="{{ 'alias.max-relation-level' | translate }}">
+ </md-input-container>
+ </div>
+ <div class="md-caption" style="color: rgba(0,0,0,0.57);" translate>relation.relation-type</div>
+ <tb-relation-type-autocomplete flex
+ hide-label
+ the-form="theForm"
+ ng-model="filter.relationType"
+ tb-required="false">
+ </tb-relation-type-autocomplete>
+ <div class="md-caption tb-required" style="color: rgba(0,0,0,0.57);" translate>entity-view.entity-view-types</div>
+ <tb-entity-subtype-list
+ tb-required="true"
+ entity-type="types.entityType.entityView"
+ ng-model="filter.entityViewTypes">
+ </tb-entity-subtype-list>
+ </section>
</div>
diff --git a/ui/src/app/entity/entity-filter-view.directive.js b/ui/src/app/entity/entity-filter-view.directive.js
index 8bd3422..5b34107 100644
--- a/ui/src/app/entity/entity-filter-view.directive.js
+++ b/ui/src/app/entity/entity-filter-view.directive.js
@@ -77,6 +77,15 @@ export default function EntityFilterViewDirective($compile, $templateCache, $q,
scope.filterDisplayValue = $translate.instant('alias.filter-type-device-type-description', {deviceType: deviceType});
}
break;
+ case types.aliasFilterType.entityViewType.value:
+ var entityViewType = scope.filter.entityViewType;
+ prefix = scope.filter.entityViewNameFilter;
+ if (prefix && prefix.length) {
+ scope.filterDisplayValue = $translate.instant('alias.filter-type-entity-view-type-and-name-description', {entityViewType: entityViewType, prefix: prefix});
+ } else {
+ scope.filterDisplayValue = $translate.instant('alias.filter-type-entity-view-type-description', {entityViewType: entityViewType});
+ }
+ break;
case types.aliasFilterType.relationsQuery.value:
var rootEntityText;
var directionText;
@@ -134,6 +143,7 @@ export default function EntityFilterViewDirective($compile, $templateCache, $q,
break;
case types.aliasFilterType.assetSearchQuery.value:
case types.aliasFilterType.deviceSearchQuery.value:
+ case types.aliasFilterType.entityViewSearchQuery.value:
allEntitiesText = $translate.instant('alias.all-entities');
anyRelationText = $translate.instant('alias.any-relation');
if (scope.filter.rootStateEntity) {
@@ -165,7 +175,7 @@ export default function EntityFilterViewDirective($compile, $templateCache, $q,
scope.filterDisplayValue = $translate.instant('alias.filter-type-asset-search-query-description',
translationValues
);
- } else {
+ } else if (scope.filter.type == types.aliasFilterType.deviceSearchQuery.value) {
var deviceTypesQuoted = [];
scope.filter.deviceTypes.forEach(function(deviceType) {
deviceTypesQuoted.push("'"+deviceType+"'");
@@ -175,6 +185,16 @@ export default function EntityFilterViewDirective($compile, $templateCache, $q,
scope.filterDisplayValue = $translate.instant('alias.filter-type-device-search-query-description',
translationValues
);
+ } else if (scope.filter.type == types.aliasFilterType.entityViewSearchQuery.value) {
+ var entityViewTypesQuoted = [];
+ scope.filter.entityViewTypes.forEach(function(entityViewType) {
+ entityViewTypesQuoted.push("'"+entityViewType+"'");
+ });
+ var entityViewTypesText = entityViewTypesQuoted.join(', ');
+ translationValues.entityViewTypes = entityViewTypesText;
+ scope.filterDisplayValue = $translate.instant('alias.filter-type-entity-view-search-query-description',
+ translationValues
+ );
}
break;
default:
diff --git a/ui/src/app/entity/entity-subtype-autocomplete.directive.js b/ui/src/app/entity/entity-subtype-autocomplete.directive.js
index 5812715..4c79f9a 100644
--- a/ui/src/app/entity/entity-subtype-autocomplete.directive.js
+++ b/ui/src/app/entity/entity-subtype-autocomplete.directive.js
@@ -22,7 +22,7 @@ import entitySubtypeAutocompleteTemplate from './entity-subtype-autocomplete.tpl
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
-export default function EntitySubtypeAutocomplete($compile, $templateCache, $q, $filter, assetService, deviceService, types) {
+export default function EntitySubtypeAutocomplete($compile, $templateCache, $q, $filter, assetService, deviceService, entityViewService, types) {
var linker = function (scope, element, attrs, ngModelCtrl) {
var template = $templateCache.get(entitySubtypeAutocompleteTemplate);
@@ -96,6 +96,8 @@ export default function EntitySubtypeAutocomplete($compile, $templateCache, $q,
entitySubtypesPromise = assetService.getAssetTypes({ignoreLoading: true});
} else if (scope.entityType == types.entityType.device) {
entitySubtypesPromise = deviceService.getDeviceTypes({ignoreLoading: true});
+ } else if (scope.entityType == types.entityType.entityView) {
+ entitySubtypesPromise = entityViewService.getEntityViewTypes({ignoreLoading: true});
}
if (entitySubtypesPromise) {
entitySubtypesPromise.then(
@@ -134,6 +136,13 @@ export default function EntitySubtypeAutocomplete($compile, $templateCache, $q,
scope.$on('deviceSaved', function() {
scope.entitySubtypes = null;
});
+ } else if (scope.entityType == types.entityType.entityView) {
+ scope.selectEntitySubtypeText = 'entity-view.select-entity-view-type';
+ scope.entitySubtypeText = 'entity-view.entity-view-type';
+ scope.entitySubtypeRequiredText = 'entity-view.entity-view-type-required';
+ scope.$on('entityViewSaved', function() {
+ scope.entitySubtypes = null;
+ });
}
}
diff --git a/ui/src/app/entity/entity-subtype-list.directive.js b/ui/src/app/entity/entity-subtype-list.directive.js
index d74a7b0..2da948d 100644
--- a/ui/src/app/entity/entity-subtype-list.directive.js
+++ b/ui/src/app/entity/entity-subtype-list.directive.js
@@ -22,7 +22,7 @@ import entitySubtypeListTemplate from './entity-subtype-list.tpl.html';
import './entity-subtype-list.scss';
/*@ngInject*/
-export default function EntitySubtypeListDirective($compile, $templateCache, $q, $mdUtil, $translate, $filter, types, assetService, deviceService) {
+export default function EntitySubtypeListDirective($compile, $templateCache, $q, $mdUtil, $translate, $filter, types, assetService, deviceService, entityViewService) {
var linker = function (scope, element, attrs, ngModelCtrl) {
@@ -97,6 +97,8 @@ export default function EntitySubtypeListDirective($compile, $templateCache, $q,
entitySubtypesPromise = assetService.getAssetTypes({ignoreLoading: true});
} else if (scope.entityType == types.entityType.device) {
entitySubtypesPromise = deviceService.getDeviceTypes({ignoreLoading: true});
+ } else if (scope.entityType == types.entityType.entityView) {
+ entitySubtypesPromise = entityViewService.getEntityViewTypes({ignoreLoading: true});
}
if (entitySubtypesPromise) {
entitySubtypesPromise.then(
diff --git a/ui/src/app/entity/entity-subtype-select.directive.js b/ui/src/app/entity/entity-subtype-select.directive.js
index b86e944..d6163da 100644
--- a/ui/src/app/entity/entity-subtype-select.directive.js
+++ b/ui/src/app/entity/entity-subtype-select.directive.js
@@ -22,7 +22,7 @@ import entitySubtypeSelectTemplate from './entity-subtype-select.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
-export default function EntitySubtypeSelect($compile, $templateCache, $translate, assetService, deviceService, types) {
+export default function EntitySubtypeSelect($compile, $templateCache, $translate, assetService, deviceService, entityViewService, types) {
var linker = function (scope, element, attrs, ngModelCtrl) {
var template = $templateCache.get(entitySubtypeSelectTemplate);
@@ -75,6 +75,8 @@ export default function EntitySubtypeSelect($compile, $templateCache, $translate
entitySubtypesPromise = assetService.getAssetTypes({ignoreLoading: true});
} else if (scope.entityType == types.entityType.device) {
entitySubtypesPromise = deviceService.getDeviceTypes({ignoreLoading: true});
+ } else if (scope.entityType == types.entityType.entityView) {
+ entitySubtypesPromise = entityViewService.getEntityViewTypes({ignoreLoading: true});
}
if (entitySubtypesPromise) {
entitySubtypesPromise.then(
diff --git a/ui/src/app/entity-view/entity-view-fieldset.tpl.html b/ui/src/app/entity-view/entity-view-fieldset.tpl.html
index 3894eb9..66dc116 100644
--- a/ui/src/app/entity-view/entity-view-fieldset.tpl.html
+++ b/ui/src/app/entity-view/entity-view-fieldset.tpl.html
@@ -52,12 +52,22 @@
<div translate ng-message="required">entity-view.name-required</div>
</div>
</md-input-container>
- <tb-entity-select flex ng-disabled="!isEdit"
- the-form="theForm"
- tb-required="true"
- allowed-entity-types="allowedEntityTypes"
- ng-model="entityView.entityId">
- </tb-entity-select>
+ <tb-entity-subtype-autocomplete
+ ng-disabled="$root.loading || !isEdit"
+ tb-required="true"
+ the-form="theForm"
+ ng-model="entityView.type"
+ entity-type="types.entityType.entityView">
+ </tb-entity-subtype-autocomplete>
+ <section layout="column">
+ <label translate class="tb-title no-padding">entity-view.related-entity</label>
+ <tb-entity-select flex ng-disabled="!isEdit"
+ the-form="theForm"
+ tb-required="true"
+ allowed-entity-types="allowedEntityTypes"
+ ng-model="entityView.entityId">
+ </tb-entity-select>
+ </section>
<md-input-container class="md-block">
<label translate>entity-view.description</label>
<textarea ng-model="entityView.additionalInfo.description" rows="2"></textarea>
diff --git a/ui/src/app/help/help-links.constant.js b/ui/src/app/help/help-links.constant.js
index 458c118..9e6bb52 100644
--- a/ui/src/app/help/help-links.constant.js
+++ b/ui/src/app/help/help-links.constant.js
@@ -96,6 +96,7 @@ export default angular.module('thingsboard.help', [])
customers: helpBaseUrl + "/docs/user-guide/ui/customers",
assets: helpBaseUrl + "/docs/user-guide/ui/assets",
devices: helpBaseUrl + "/docs/user-guide/ui/devices",
+ entityViews: helpBaseUrl + "/docs/user-guide/ui/entity-views",
dashboards: helpBaseUrl + "/docs/user-guide/ui/dashboards",
users: helpBaseUrl + "/docs/user-guide/ui/users",
widgetsBundles: helpBaseUrl + "/docs/user-guide/ui/widget-library#bundles",
diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json
index 3e9ad82..55a1722 100644
--- a/ui/src/app/locale/locale.constant-en_US.json
+++ b/ui/src/app/locale/locale.constant-en_US.json
@@ -158,12 +158,17 @@
"filter-type-device-type": "Device type",
"filter-type-device-type-description": "Devices of type '{{deviceType}}'",
"filter-type-device-type-and-name-description": "Devices of type '{{deviceType}}' and with name starting with '{{prefix}}'",
+ "filter-type-entity-view-type": "Entity View type",
+ "filter-type-entity-view-type-description": "Entity Views of type '{{entityView}}'",
+ "filter-type-entity-view-type-and-name-description": "Entity Views of type '{{entityView}}' and with name starting with '{{prefix}}'",
"filter-type-relations-query": "Relations query",
"filter-type-relations-query-description": "{{entities}} that have {{relationType}} relation {{direction}} {{rootEntity}}",
"filter-type-asset-search-query": "Asset search query",
"filter-type-asset-search-query-description": "Assets with types {{assetTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}",
"filter-type-device-search-query": "Device search query",
"filter-type-device-search-query-description": "Devices with types {{deviceTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}",
+ "filter-type-entity-view-search-query": "Entity view search query",
+ "filter-type-entity-view-search-query-description": "Entity views with types {{entityViewTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}",
"entity-filter": "Entity filter",
"resolve-multiple": "Resolve as multiple entities",
"filter-type": "Filter type",
@@ -839,7 +844,8 @@
"client-attributes": "Client attributes",
"shared-attributes": "Shared attributes",
"server-attributes": "Server attributes",
- "latest-timeseries": "Latest timeseries"
+ "latest-timeseries": "Latest timeseries",
+ "related-entity": "Related entity"
},
"event": {
"event-type": "Event type",
ui/src/app/locale/locale.constant-es_ES.json 2104(+1171 -933)
diff --git a/ui/src/app/locale/locale.constant-es_ES.json b/ui/src/app/locale/locale.constant-es_ES.json
index 729e4ff..ec0e227 100644
--- a/ui/src/app/locale/locale.constant-es_ES.json
+++ b/ui/src/app/locale/locale.constant-es_ES.json
@@ -2,9 +2,9 @@
"access": {
"unauthorized": "No autorizado",
"unauthorized-access": "Acceso no autorizado",
- "unauthorized-access-text": "Debes iniciar sesión para tener acceso a este recurso!",
+ "unauthorized-access-text": "Debe registrarse para tener acceso a este recurso!",
"access-forbidden": "Acceso Prohibido",
- "access-forbidden-text": "No tienes derechos para acceder a esta ubicación!<br/>Intenta iniciar sesión con otro usuario si todavía quieres acceder a esta ubicación.",
+ "access-forbidden-text": "No tiene derechos para acceder a esta ubicación!<br/>Intente registrarse con otro usuario si aún desea acceder a esta ubicación.",
"refresh-token-expired": "La sesión ha expirado",
"refresh-token-failed": "No se puede actualizar la sesión"
},
@@ -15,342 +15,374 @@
"saveAs": "Guardar como",
"cancel": "Cancelar",
"ok": "OK",
- "delete": "Borrar",
+ "delete": "Eliminar",
"add": "Agregar",
"yes": "Si",
"no": "No",
"update": "Actualizar",
"remove": "Eliminar",
"search": "Buscar",
+ "clear-search": "Borrar búsqueda",
"assign": "Asignar",
- "unassign": "Cancelar asignación",
+ "unassign": "Anular asignación",
"share": "Compartir",
"make-private": "Hacer privado",
"apply": "Aplicar",
"apply-changes": "Aplicar cambios",
- "edit-mode": "Modo Edición",
- "enter-edit-mode": "Modo Edición",
+ "edit-mode": "Modo edición",
+ "enter-edit-mode": "Ingresar modo edición",
"decline-changes": "Descartar cambios",
"close": "Cerrar",
- "back": "Atrás",
- "run": "Correr",
- "sign-in": "Regístrate!",
+ "back": "Atras",
+ "run": "Ejecutar",
+ "sign-in": "Registrarse!",
"edit": "Editar",
"view": "Ver",
"create": "Crear",
"drag": "Arrastrar",
- "refresh": "Refrescar",
+ "refresh": "Refrecar",
"undo": "Deshacer",
"copy": "Copiar",
"paste": "Pegar",
+ "copy-reference": "Copiar referencia",
+ "paste-reference": "Pegar referencia",
"import": "Importar",
"export": "Exportar",
- "share-via": "Compartir vía {{provider}}"
+ "share-via": "Share via {{provider}}"
},
"aggregation": {
"aggregation": "Agregación",
- "function": "Función de Agregación",
- "limit": "Valores Max",
- "group-interval": "Intervalo de agrupación",
+ "function": "Función de agregación de datos",
+ "limit": "Valores máximos",
+ "group-interval": "Intervalo de agrupamiento",
"min": "Min",
"max": "Max",
"avg": "Promedio",
"sum": "Suma",
- "count": "Cuenta",
+ "count": "Contar",
"none": "Ninguno"
},
"admin": {
"general": "General",
- "general-settings": "Ajustes General",
- "outgoing-mail": "Mail de Salida",
- "outgoing-mail-settings": "Ajustes del Mail de Salida",
- "system-settings": "Sistema",
- "test-mail-sent": "Mail de prueba enviado correctamente!",
- "base-url": "URL Base",
- "base-url-required": "URL Base requerida.",
- "mail-from": "Mail Desde",
- "mail-from-required": "Mail Desde requerido.",
+ "general-settings": "Configuración general",
+ "outgoing-mail": "Servidor de correo",
+ "outgoing-mail-settings": "Configuración del servidor de correo de salida",
+ "system-settings": "Configuración del sistema",
+ "test-mail-sent": "Correo de prueba fue enviado exitosamente!",
+ "base-url": "URL base",
+ "base-url-required": "URL base es requerida.",
+ "mail-from": "Correo desde",
+ "mail-from-required": "Correo Desde es requerido.",
"smtp-protocol": "Protocolo SMTP",
"smtp-host": "Host SMTP",
- "smtp-host-required": "Host SMTP requerido.",
+ "smtp-host-required": "Host SMTP es requerido.",
"smtp-port": "Puerto SMTP",
- "smtp-port-required": "Debe ingresar un Puerto SMTP.",
- "smtp-port-invalid": "No parece un Puerto SMTP valido.",
- "timeout-msec": "Timeout (ms)",
- "timeout-required": "Timeout requerido.",
- "timeout-invalid": "No parece un Timeout valido.",
+ "smtp-port-required": "Debe suministrar un puerto SMTP",
+ "smtp-port-invalid": "Eso no parece un puerto SMTP válido.",
+ "timeout-msec": "Tiempo de espera (ms)",
+ "timeout-required": "Tiempo de espera es requerido.",
+ "timeout-invalid": "Eso no parece un tiempo de espera válido.",
"enable-tls": "Habilitar TLS",
- "send-test-mail": "Enviar mail de prueba"
+ "send-test-mail": "Enviar correo de prueba"
},
"alarm": {
- "alarm": "Alarm",
- "alarms": "Alarms",
- "select-alarm": "Select alarm",
- "no-alarms-matching": "No alarms matching '{{entity}}' were found.",
- "alarm-required": "Alarm is required",
- "alarm-status": "Alarm status",
+ "alarm": "Alarma",
+ "alarms": "Alarmas",
+ "select-alarm": "Seleccionar alarma",
+ "no-alarms-matching": "Alarmas que coincidan con '{{entity}}' no fueron encontradas.",
+ "alarm-required": "Alarma es requerida",
+ "alarm-status": "Estado de la alarma",
"search-status": {
- "ANY": "Any",
- "ACTIVE": "Active",
- "CLEARED": "Cleared",
- "ACK": "Acknowledged",
- "UNACK": "Unacknowledged"
+ "ANY": "Alguna",
+ "ACTIVE": "Activa",
+ "CLEARED": "Borrada",
+ "ACK": "Reconocida",
+ "UNACK": "Ignorada"
},
"display-status": {
- "ACTIVE_UNACK": "Active Unacknowledged",
- "ACTIVE_ACK": "Active Acknowledged",
- "CLEARED_UNACK": "Cleared Unacknowledged",
- "CLEARED_ACK": "Cleared Acknowledged"
+ "ACTIVE_UNACK": "Activa ignorada",
+ "ACTIVE_ACK": "Activa reconocida",
+ "CLEARED_UNACK": "Borrada ignorada",
+ "CLEARED_ACK": "Borrada reconocida"
},
- "no-alarms-prompt": "No alarms found",
- "created-time": "Created time",
- "type": "Type",
- "severity": "Severity",
- "originator": "Originator",
- "originator-type": "Originator type",
- "details": "Details",
- "status": "Status",
- "alarm-details": "Alarm details",
- "start-time": "Start time",
- "end-time": "End time",
- "ack-time": "Acknowledged time",
- "clear-time": "Cleared time",
- "severity-critical": "Critical",
- "severity-major": "Major",
- "severity-minor": "Minor",
- "severity-warning": "Warning",
- "severity-indeterminate": "Indeterminate",
- "acknowledge": "Acknowledge",
- "clear": "Clear",
- "search": "Search alarms",
- "selected-alarms": "{ count, plural, 1 {1 alarm} other {# alarms} } selected",
- "no-data": "No data to display",
- "polling-interval": "Alarms polling interval (sec)",
- "polling-interval-required": "Alarms polling interval is required.",
- "min-polling-interval-message": "At least 1 sec polling interval is allowed.",
- "aknowledge-alarms-title": "Acknowledge { count, plural, 1 {1 alarm} other {# alarms} }",
- "aknowledge-alarms-text": "Are you sure you want to acknowledge { count, plural, 1 {1 alarm} other {# alarms} }?",
- "clear-alarms-title": "Clear { count, plural, 1 {1 alarm} other {# alarms} }",
- "clear-alarms-text": "Are you sure you want to clear { count, plural, 1 {1 alarm} other {# alarms} }?"
+ "no-alarms-prompt": "Alarmas no encontradas",
+ "created-time": "Tiempo de creación",
+ "type": "Tipo",
+ "severity": "Severidad",
+ "originator": "Origen",
+ "originator-type": "Tipo de origen",
+ "details": "Detalles",
+ "status": "Estado",
+ "alarm-details": "Detalles de la alarma",
+ "start-time": "Tiempo de inicio",
+ "end-time": "Tiempo de finalización",
+ "ack-time": "Tiempo de reconocimiento",
+ "clear-time": "Tiempo de borrado",
+ "severity-critical": "Crítica",
+ "severity-major": "Mayor",
+ "severity-minor": "Menor",
+ "severity-warning": "Alerta",
+ "severity-indeterminate": "Indeterminada",
+ "acknowledge": "Reconocer",
+ "clear": "Borrar",
+ "search": "buscar alarmas",
+ "selected-alarms": "{ count, plural, 1 {1 alarm} other {# alarms} } seleccionadas",
+ "no-data": "No hay datos para mostrar",
+ "polling-interval": "Intervalo de sondeo de alarmas (seg)",
+ "polling-interval-required": "Intervalo de sondeo de alarmas es requerido.",
+ "min-polling-interval-message": "Se permite al menos 1 segundo de intervalo de sondeo.",
+ "aknowledge-alarms-title": "Reconocer { count, plural, 1 {1 alarm} other {# alarms} }",
+ "aknowledge-alarms-text": "¿Está seguro de que desea reconocer { count, plural, 1 {1 alarm} other {# alarms} }?",
+ "aknowledge-alarm-title": "Acknowledge Alarm",
+ "aknowledge-alarm-text": "Are you sure you want to acknowledge Alarm?",
+ "clear-alarms-title": "Borrar { count, plural, 1 {1 alarm} other {# alarms} }",
+ "clear-alarms-text": "¿Está seguro de que desea borrar { count, plural, 1 {1 alarm} other {# alarms} }?",
+ "clear-alarm-title": "Clear Alarm",
+ "clear-alarm-text": "Are you sure you want to clear Alarm?",
+ "alarm-status-filter": "Alarm Status Filter"
},
"alias": {
- "add": "Add alias",
- "edit": "Edit alias",
- "name": "Alias name",
- "name-required": "Alias name is required",
- "duplicate-alias": "Alias with same name is already exists.",
- "filter-type-single-entity": "Single entity",
- "filter-type-entity-list": "Entity list",
- "filter-type-entity-name": "Entity name",
- "filter-type-state-entity": "Entity from dashboard state",
- "filter-type-state-entity-description": "Entity taken from dashboard state parameters",
- "filter-type-asset-type": "Asset type",
- "filter-type-asset-type-description": "Assets of type '{{assetType}}'",
- "filter-type-asset-type-and-name-description": "Assets of type '{{assetType}}' and with name starting with '{{prefix}}'",
- "filter-type-device-type": "Device type",
- "filter-type-device-type-description": "Devices of type '{{deviceType}}'",
- "filter-type-device-type-and-name-description": "Devices of type '{{deviceType}}' and with name starting with '{{prefix}}'",
- "filter-type-relations-query": "Relations query",
- "filter-type-relations-query-description": "{{entities}} that have {{relationType}} relation {{direction}} {{rootEntity}}",
- "filter-type-asset-search-query": "Asset search query",
- "filter-type-asset-search-query-description": "Assets with types {{assetTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}",
- "filter-type-device-search-query": "Device search query",
- "filter-type-device-search-query-description": "Devices with types {{deviceTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}",
- "entity-filter": "Entity filter",
- "resolve-multiple": "Resolve as multiple entities",
- "filter-type": "Filter type",
- "filter-type-required": "Filter type is required.",
- "entity-filter-no-entity-matched": "No entities matching specified filter were found.",
- "no-entity-filter-specified": "No entity filter specified",
- "root-state-entity": "Use dashboard state entity as root",
- "root-entity": "Root entity",
- "state-entity-parameter-name": "State entity parameter name",
- "default-state-entity": "Default state entity",
- "default-entity-parameter-name": "By default",
- "max-relation-level": "Max relation level",
- "unlimited-level": "Unlimited level",
- "state-entity": "Dashboard state entity",
- "all-entities": "All entities",
- "any-relation": "any"
+ "add": "Agregar alias",
+ "edit": "Editar alias",
+ "name": "Nombre de alias",
+ "name-required": "Nombre de alias es requerido",
+ "duplicate-alias": "Ya existe un alias con el mismo nombre.",
+ "filter-type-single-entity": "Entidad única",
+ "filter-type-entity-list": "Lista de entidades",
+ "filter-type-entity-name": "Nombre de entidad",
+ "filter-type-state-entity": "Entidad del panel de estados",
+ "filter-type-state-entity-description": "Entidad tomada desde los parámetro del panel de estados",
+ "filter-type-asset-type": "Tipo de activo",
+ "filter-type-asset-type-description": "Activos de tipo '{{assetType}}'",
+ "filter-type-asset-type-and-name-description": "Activos de tipo '{{assetType}}' y con nombre comenzando con '{{prefix}}'",
+ "filter-type-device-type": "Tipo de dispositivo",
+ "filter-type-device-type-description": "Dispositivos de tipo '{{deviceType}}'",
+ "filter-type-device-type-and-name-description": "Dispositivos de tipo '{{deviceType}}' y con nombre comenzando con '{{prefix}}'",
+ "filter-type-relations-query": "Consulta de relaciones",
+ "filter-type-relations-query-description": "{{entities}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}",
+ "filter-type-asset-search-query": "Consultar búsqueda de activos",
+ "filter-type-asset-search-query-description": "Activos con tipos {{assetTypes}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}",
+ "filter-type-device-search-query": "Consultar búqueda de dispositivos",
+ "filter-type-device-search-query-description": "Dispositivos con tipos {{deviceTypes}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}",
+ "entity-filter": "Filtro de entidad",
+ "resolve-multiple": "Resolver como entidades múltiples",
+ "filter-type": "Tipo de filtro",
+ "filter-type-required": "Tipo de filtro es requerido.",
+ "entity-filter-no-entity-matched": "Entidades que coincidan con el filtro especificado no fueron encontradas.",
+ "no-entity-filter-specified": "No se especificó el filtro de entidad",
+ "root-state-entity": "Utilizar la entidad del panel de estados como raíz",
+ "root-entity": "Entidad raíz",
+ "state-entity-parameter-name": "Nombre de parámetro de entidad de estado",
+ "default-state-entity": "Entidad de estado predeterminada",
+ "default-entity-parameter-name": "Por defecto",
+ "max-relation-level": "Nivel máximo de relación",
+ "unlimited-level": "Nivel ilimitado",
+ "state-entity": "Entidad del panel de estados",
+ "all-entities": "Todas las entidades",
+ "any-relation": "alguna"
},
"asset": {
- "asset": "Asset",
- "assets": "Assets",
- "management": "Asset management",
- "view-assets": "View Assets",
- "add": "Add Asset",
- "assign-to-customer": "Assign to customer",
- "assign-asset-to-customer": "Assign Asset(s) To Customer",
- "assign-asset-to-customer-text": "Please select the assets to assign to the customer",
- "no-assets-text": "No assets found",
- "assign-to-customer-text": "Please select the customer to assign the asset(s)",
- "public": "Public",
- "assignedToCustomer": "Assigned to customer",
- "make-public": "Make asset public",
- "make-private": "Make asset private",
- "unassign-from-customer": "Unassign from customer",
- "delete": "Delete asset",
- "asset-public": "Asset is public",
- "asset-type": "Asset type",
- "asset-type-required": "Asset type is required.",
- "select-asset-type": "Select asset type",
- "enter-asset-type": "Enter asset type",
- "any-asset": "Any asset",
- "no-asset-types-matching": "No asset types matching '{{entitySubtype}}' were found.",
- "asset-type-list-empty": "No asset types selected.",
- "asset-types": "Asset types",
- "name": "Name",
- "name-required": "Name is required.",
- "description": "Description",
- "type": "Type",
- "type-required": "Type is required.",
- "details": "Details",
- "events": "Events",
- "add-asset-text": "Add new asset",
- "asset-details": "Asset details",
- "assign-assets": "Assign assets",
- "assign-assets-text": "Assign { count, plural, 1 {1 asset} other {# assets} } to customer",
- "delete-assets": "Delete assets",
- "unassign-assets": "Unassign assets",
- "unassign-assets-action-title": "Unassign { count, plural, 1 {1 asset} other {# assets} } from customer",
- "assign-new-asset": "Assign new asset",
- "delete-asset-title": "Are you sure you want to delete the asset '{{assetName}}'?",
- "delete-asset-text": "Be careful, after the confirmation the asset and all related data will become unrecoverable.",
- "delete-assets-title": "Are you sure you want to delete { count, plural, 1 {1 asset} other {# assets} }?",
- "delete-assets-action-title": "Delete { count, plural, 1 {1 asset} other {# assets} }",
- "delete-assets-text": "Be careful, after the confirmation all selected assets will be removed and all related data will become unrecoverable.",
- "make-public-asset-title": "Are you sure you want to make the asset '{{assetName}}' public?",
- "make-public-asset-text": "After the confirmation the asset and all its data will be made public and accessible by others.",
- "make-private-asset-title": "Are you sure you want to make the asset '{{assetName}}' private?",
- "make-private-asset-text": "After the confirmation the asset and all its data will be made private and won't be accessible by others.",
- "unassign-asset-title": "Are you sure you want to unassign the asset '{{assetName}}'?",
- "unassign-asset-text": "After the confirmation the asset will be unassigned and won't be accessible by the customer.",
- "unassign-asset": "Unassign asset",
- "unassign-assets-title": "Are you sure you want to unassign { count, plural, 1 {1 asset} other {# assets} }?",
- "unassign-assets-text": "After the confirmation all selected assets will be unassigned and won't be accessible by the customer.",
- "copyId": "Copy asset Id",
- "idCopiedMessage": "Asset Id has been copied to clipboard",
- "select-asset": "Select asset",
- "no-assets-matching": "No assets matching '{{entity}}' were found.",
- "asset-required": "Asset is required",
- "name-starts-with": "Asset name starts with"
+ "asset": "Activo",
+ "assets": "Activos",
+ "management": "Gestión de activos",
+ "view-assets": "Ver Activos",
+ "add": "Agregar Activo",
+ "assign-to-customer": "Asignar al cliente",
+ "assign-asset-to-customer": "Asignar Activo(s) Al Cliente",
+ "assign-asset-to-customer-text": "Por favor seleccionar los activos para asignar al cliente",
+ "no-assets-text": "Activos no encontrados",
+ "assign-to-customer-text": "Por favor seleccionar el cliente para asignar el(los) activo(s)",
+ "public": "Público",
+ "assignedToCustomer": "Asignado al cliente",
+ "make-public": "Hacer público el activo",
+ "make-private": "Hacer privado el activo",
+ "unassign-from-customer": "Anular asignación del cliente",
+ "delete": "Eliminar activo",
+ "asset-public": "El activo es público",
+ "asset-type": "Tipo de activo",
+ "asset-type-required": "El tipo de activo es requerido.",
+ "select-asset-type": "Seleccionar tipo de activo",
+ "enter-asset-type": "Ingresar tipo de activo",
+ "any-asset": "Algún activo",
+ "no-asset-types-matching": "Tipos de activos que coincidan con '{{entitySubtype}}' no fueron encontrados.",
+ "asset-type-list-empty": "No se seleccionaron tipos de activos.",
+ "asset-types": "Tipos de activos",
+ "name": "Nombre",
+ "name-required": "El nombre es requerido.",
+ "description": "Descripción",
+ "type": "Tipo",
+ "type-required": "El tipo es requerido.",
+ "details": "Detalles",
+ "events": "Eventos",
+ "add-asset-text": "Agregar nuevos activos",
+ "asset-details": "Detalles del activo",
+ "assign-assets": "Asignar activos",
+ "assign-assets-text": "Asignar { count, plural, 1 {1 asset} other {# assets} } al cliente",
+ "delete-assets": "Eliminar activos",
+ "unassign-assets": "Anular asignación de activos",
+ "unassign-assets-action-title": "Anular asignación { count, plural, 1 {1 asset} other {# assets} } del cliente",
+ "assign-new-asset": "Asignar nuevo activo",
+ "delete-asset-title": "¿Está seguro de que desea eliminar el activo '{{assetName}}'?",
+ "delete-asset-text": "Tener cuidado, después de la confirmación, el activo y todos los datos relacionados se volverán irrecuperables.",
+ "delete-assets-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 asset} other {# assets} }?",
+ "delete-assets-action-title": "Eliminar { count, plural, 1 {1 asset} other {# assets} }",
+ "delete-assets-text": "Tener cuidado, después de la confirmación se eliminarán todos los activos seleccionados y todos los datos relacionados se volverán irrecuperables.",
+ "make-public-asset-title": "¿Está seguro de que desea que el activo '{{assetName}}' sea público?",
+ "make-public-asset-text": "Después de la confirmación, el activo y todos sus datos se harán públicos y accesibles por otros.",
+ "make-private-asset-title": "¿Está seguro de que desea que el activo '{{assetName}}' sea privado?",
+ "make-private-asset-text": "Después de la confirmación, el activo y todos sus datos se harán privados y no serán accesibles para otros",
+ "unassign-asset-title": "¿Está seguro de que desea anular asignación del activo '{{assetName}}'?",
+ "unassign-asset-text": "Después de la confirmación, se anulará asignación del activo y no será accesible por el cliente.",
+ "unassign-asset": "Anular asignación activo",
+ "unassign-assets-title": "¿Está seguro de que desea anular asignación { count, plural, 1 {1 asset} other {# assets} }?",
+ "unassign-assets-text": "Después de la confirmación, se anulará asignación de todos los activos seleccionados y no serán accesibles por el cliente",
+ "copyId": "Copiar ID del activo",
+ "idCopiedMessage": "ID del activo has sido copiada al portapapeles",
+ "select-asset": "Seleccionar activo",
+ "no-assets-matching": "Activos que coincidan con '{{entity}}' no fueron encontrados.",
+ "asset-required": "El activo es requerido",
+ "name-starts-with": "El nombre del activo comienza con"
},
"attribute": {
"attributes": "Atributos",
"latest-telemetry": "Última telemetría",
- "attributes-scope": "Alcance de los atributos del dispositivo",
+ "attributes-scope": "Alcance de los atributos de la entidad",
"scope-latest-telemetry": "Última telemetría",
- "scope-client": "Atributos del Cliente",
- "scope-server": "Atributos del Servidor",
- "scope-shared": "Atributos Compartidos",
- "add": "Agregar atributo",
+ "scope-client": "Atributos del cliente",
+ "scope-server": "Atributos del servidor",
+ "scope-shared": "Atributos compartidos",
+ "add": "Agregar atributos",
"key": "Clave",
- "key-required": "Clave del atributo requerida.",
+ "last-update-time": "Hora de la última actualización",
+ "key-required": "La clave del aributo es requerida.",
"value": "Valor",
- "value-required": "Valor del atributo requerido.",
- "delete-attributes-title": "¿Estás seguro que quieres eliminar { count, plural, 1 {1 atributo} other {# atributos} }?",
- "delete-attributes-text": "Ten cuidado, luego de confirmar el atributo será eliminado, y la información relacionada será irrecuperable.",
- "delete-attributes": "Borrar atributo",
+ "value-required": "Valor del atributo es requerido.",
+ "delete-attributes-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 attribute} other {# attributes} }?",
+ "delete-attributes-text": "Tener cuidado, después de la confirmación, se eliminarán todos los atributos seleccionados.",
+ "delete-attributes": "Eliminar atributos",
"enter-attribute-value": "Ingresar valor del atributo",
- "show-on-widget": "Mostrar en Widget",
- "widget-mode": "Widget",
+ "show-on-widget": "Mostrar en widget",
+ "widget-mode": "Modo widget",
"next-widget": "Widget siguiente",
- "prev-widget": "Widget anterior",
- "add-to-dashboard": "Agregar al Panel",
- "add-widget-to-dashboard": "Agregar widget al Panel",
- "selected-attributes": "{ count, plural, 1 {1 atributo} other {# atributos} } seleccionados",
- "selected-telemetry": "{ count, plural, 1 {1 unidad de telemetría } other {# unidades de telemetría} } seleccionadas."
+ "prev-widget": "Widget previo",
+ "add-to-dashboard": "Agregar al panel",
+ "add-widget-to-dashboard": "Agregar widget al panel",
+ "selected-attributes": "{ count, plural, 1 {1 attribute} other {# attributes} } seleccionados",
+ "selected-telemetry": "{ count, plural, 1 {1 telemetry unit} other {# telemetry units} } seleccionadas"
},
"audit-log": {
- "audit": "Audit",
- "audit-logs": "Audit Logs",
- "timestamp": "Timestamp",
- "entity-type": "Entity Type",
- "entity-name": "Entity Name",
- "user": "User",
- "type": "Type",
- "status": "Status",
- "details": "Details",
- "type-added": "Added",
- "type-deleted": "Deleted",
- "type-updated": "Updated",
- "type-attributes-updated": "Attributes updated",
- "type-attributes-deleted": "Attributes deleted",
- "type-rpc-call": "RPC call",
- "type-credentials-updated": "Credentials updated",
- "type-assigned-to-customer": "Assigned to Customer",
- "type-unassigned-from-customer": "Unassigned from Customer",
- "type-activated": "Activated",
- "type-suspended": "Suspended",
- "type-credentials-read": "Credentials read",
- "type-attributes-read": "Attributes read",
- "status-success": "Success",
- "status-failure": "Failure",
- "audit-log-details": "Audit log details",
- "no-audit-logs-prompt": "No logs found",
- "action-data": "Action data",
- "failure-details": "Failure details",
- "search": "Search audit logs",
- "clear-search": "Clear search"
+ "audit": "Auditar",
+ "audit-logs": "Auditar Registros",
+ "timestamp": "Marca de tiempo",
+ "entity-type": "Tipo de Entidad",
+ "entity-name": "Nombre de Entidad",
+ "user": "Usuario",
+ "type": "Tipo",
+ "status": "Estado",
+ "details": "Detalles",
+ "type-added": "Agregado",
+ "type-deleted": "Eliminado",
+ "type-updated": "Actualizado",
+ "type-attributes-updated": "Atributos actualizados",
+ "type-attributes-deleted": "Atributos eliminados",
+ "type-rpc-call": "Llamada RPC",
+ "type-credentials-updated": "Credenciales actualizadas",
+ "type-assigned-to-customer": "Asignado al Cliente",
+ "type-unassigned-from-customer": "Asignación anulada del cliente",
+ "type-activated": "Activado",
+ "type-suspended": "Suspendido",
+ "type-credentials-read": "Credenciales leídas",
+ "type-attributes-read": "Atributos leídos",
+ "type-relation-add-or-update": "Relación actualizada",
+ "type-relation-delete": "Relación eliminada",
+ "type-relations-delete": "Toda relación eliminada",
+ "type-alarm-ack": "Reconocida",
+ "type-alarm-clear": "Borrada",
+ "status-success": "Éxito",
+ "status-failure": "Falla",
+ "audit-log-details": "Auditar detalles de regisstro",
+ "no-audit-logs-prompt": "Registros no encontrados",
+ "action-data": "Datos de acción",
+ "failure-details": "Detalles de falla",
+ "search": "Buscar registros de auditoría",
+ "clear-search": "Borrar búsqueda"
},
"confirm-on-exit": {
- "message": "Tienes cambios sin guardar. ¿Estás seguro que quieres abandonar la página?",
- "html-message": "Tienes cambios sin guardar.<br/>¿Estás seguro que quieres abandonar la página?",
+ "message": "Tiene cambios sin guardar. ¿Está seguro de que desea salir de esta página?",
+ "html-message": "Tiene cambios sin guardar..<br/>¿Está seguro de que desea salir de esta página?",
"title": "Cambios sin guardar"
},
"contact": {
"country": "País",
"city": "Ciudad",
- "state": "Estado/Provincia",
+ "state": "Estado / Provincia",
"postal-code": "Código Postal",
- "postal-code-invalid": "Solo se permiten dígitos.",
+ "postal-code-invalid": "Formato de código postal inválido.",
"address": "Dirección",
"address2": "Dirección 2",
"phone": "Teléfono",
- "email": "Email",
- "no-address": "Sin Dirección"
+ "email": "Correo Electrónico",
+ "no-address": "Sin dirección"
},
"common": {
- "username": "Usuario",
+ "username": "Nombre de usuario",
"password": "Contraseña",
- "enter-username": "Ingresa el nombre de usuario.",
- "enter-password": "Ingresa la contraseña",
- "enter-search": "Ingresa búsqueda"
+ "enter-username": "Ingresar nombre de usuario",
+ "enter-password": "Ingresar contraseña",
+ "enter-search": "Ingresar búsqueda"
},
"content-type": {
"json": "Json",
- "text": "Text",
- "binary": "Binary (Base64)"
+ "text": "Texto",
+ "binary": "Binario (Base64)"
},
"customer": {
+ "customer": "Cliente",
"customers": "Clientes",
- "management": "Gestión de Clientes",
+ "management": "Gestión del cliente",
"dashboard": "Panel del Cliente",
"dashboards": "Paneles del Cliente",
- "devices": "Panel del Cliente",
+ "devices": "Dispositivos del Cliente",
+ "entity-views": "Customer Entity Views",
+ "assets": "Activos del Cliente",
"public-dashboards": "Paneles Públicos",
"public-devices": "Dispositivos Públicos",
+ "public-assets": "Activos Públicos",
+ "public-entity-views": "Public Entity Views",
"add": "Agregar cliente",
- "delete": "Borrar cliente",
+ "delete": "Eliminar cliente",
"manage-customer-users": "Gestionar usuarios del cliente",
"manage-customer-devices": "Gestionar dispositivos del cliente",
"manage-customer-dashboards": "Gestionar paneles del cliente",
"manage-public-devices": "Gestionar dispositivos públicos",
"manage-public-dashboards": "Gestionar paneles públicos",
+ "manage-customer-assets": "Gestionar activos del cliente",
+ "manage-public-assets": "Gestionar activos públicos",
"add-customer-text": "Agregar nuevo cliente",
- "no-customers-text": "No se encontrar clientes",
+ "no-customers-text": "Clientes no encontrados",
"customer-details": "Detalles del cliente",
- "delete-customer-title": "¿Estás seguro que quieres eliminar el cliente '{{customerTitle}}'?",
- "delete-customer-text": "Ten cuidado, luego de confirmar el cliente será eliminado y toda la información relacionada será irrecuperable.",
- "delete-customers-title": "¿Estás seguro que quieres eliminar { count, plural, 1 {1 cliente} other {# clientes} }?",
- "delete-customers-action-title": "Borrar { count, plural, 1 {1 cliente} other {# clientes} }",
- "delete-customers-text": "Ten cuidado, luego de confirmar todos los clientes seleccionados serán eliminados y su información relacionada será irrecuperable.",
+ "delete-customer-title": "¿Está seguro de que desea eliminar al cliente '{{customerTitle}}'?",
+ "delete-customer-text": "Tener cuidado, después de la confirmación, el cliente y todos los datos relacionados se volverán irrecuperables.",
+ "delete-customers-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 customer} other {# customers} }?",
+ "delete-customers-action-title": "Eliminar { count, plural, 1 {1 customer} other {# customers} }",
+ "delete-customers-text": "Tener cuidado, después de la confirmación, todos los clientes seleccionados serán eliminados y todos los datos relacionados se volverán irrecuperables.",
"manage-users": "Gestionar usuarios",
+ "manage-assets": "Gestionar activos",
"manage-devices": "Gestionar dispositivos",
"manage-dashboards": "Gestionar paneles",
"title": "Título",
- "title-required": "Título requerido.",
- "description": "Descripción"
+ "title-required": "El título es requerido.",
+ "description": "Descripción",
+ "details": "Detalles",
+ "events": "Eventos",
+ "copyId": "Copiar ID del cliente",
+ "idCopiedMessage": "ID del cliente ha sido copiada al portapapeles",
+ "select-customer": "Seleccionar cliente",
+ "no-customers-matching": "Clientes que coincidan con '{{entity}}' no fueron encontrados.",
+ "customer-required": "El cliente es requerido",
+ "select-default-customer": "Seleccionar cliente predeterminado",
+ "default-customer": "Cliente predeterminado",
+ "default-customer-required": "Cliente predeterminado es requerido para depurar el panel en el nivel Organización"
},
"datetime": {
"date-from": "Fecha desde",
@@ -361,582 +393,733 @@
"dashboard": {
"dashboard": "Panel",
"dashboards": "Paneles",
- "management": "Gestión de Paneles",
- "view-dashboards": "Ver paneles",
- "add": "Agregar Panel",
- "assign-dashboard-to-customer": "Asignar panel(es) a cliente",
- "assign-dashboard-to-customer-text": "Por favor, seleccione algún panel para asignar al Cliente.",
- "assign-to-customer-text": "Por favor, seleccione algún cliente para asignar al(los) panel(es).",
- "assign-to-customer": "Asignar a cliente",
- "unassign-from-customer": "Desasignar del cliente",
+ "management": "Gestión del panel",
+ "view-dashboards": "Ver Panel",
+ "add": "Agregar Paneles",
+ "assign-dashboard-to-customer": "Asignar Panel(es) Al Cliente",
+ "assign-dashboard-to-customer-text": "Por favor seleccionar los paneles para asignar al cliente",
+ "assign-to-customer-text": "Por favor seleccionar el cliente para asignar el(los) panel(es)",
+ "assign-to-customer": "Asignar al cliente",
+ "unassign-from-customer": "Anular asignación del cliente",
"make-public": "Hacer panel público",
- "make-private": "Hacer panel privado",
- "no-dashboards-text": "Ningún panel encontrado",
- "no-widgets": "Ningún widget configurado",
+ "make-private": "Hcer panel privado",
+ "manage-assigned-customers": "Gestionar clientes asignados",
+ "assigned-customers": "Clientes asignados",
+ "assign-to-customers": "Asignar Panel(es) Al(Los) Cliente(s)",
+ "assign-to-customers-text": "Por favor seleccionar los clientes para asignar el(los) panel(es)",
+ "unassign-from-customers": "Anular Asignación Del(De Los) Panel(es) De Los Clientes",
+ "unassign-from-customers-text": "Por favor seeccionar los clientes oara anular asignación del(de los) panel(es)",
+ "no-dashboards-text": "Paneles no encontrados",
+ "no-widgets": "Sin widgets configurados",
"add-widget": "Agregar nuevo widget",
- "title": "Titulo",
+ "title": "Título",
"select-widget-title": "Seleccionar widget",
- "select-widget-subtitle": "Lista de tipos de widgets",
+ "select-widget-subtitle": "Lista de tipos de widget disponibles",
"delete": "Eliminar panel",
- "title-required": "Título requerido.",
+ "title-required": "El título es requerido.",
"description": "Descripción",
"details": "Detalles",
- "dashboard-details": "Detalles del panel",
+ "dashboard-details": "Detalles del Panel",
"add-dashboard-text": "Agregar nuevo panel",
"assign-dashboards": "Asignar paneles",
- "assign-new-dashboard": "Asignar nuevo panel",
- "assign-dashboards-text": "Asignar { count, plural, 1 {1 panel} other {# paneles} } al cliente",
+ "assign-new-dashboard": "Aignar nuevo panel",
+ "assign-dashboards-text": "Asignar { count, plural, 1 {1 dashboard} other {# dashboards} } a los clientes",
+ "unassign-dashboards-action-text": "Anular asignación { count, plural, 1 {1 dashboard} other {# dashboards} } de los clientes",
"delete-dashboards": "Eliminar paneles",
- "unassign-dashboards": "Desasignar paneles",
- "unassign-dashboards-action-title": "Desasignar { count, plural, 1 {1 paneles} other {# paneles} } del cliente",
- "delete-dashboard-title": "¿Estás seguro que quieres eliminar el panel '{{dashboardTitle}}'?",
- "delete-dashboard-text": "Ten cuidado, el panel seleccionado será eliminado y la información relacionada sera irrecuperable.",
- "delete-dashboards-title": "¿Estás seguro que quieres eliminar { count, plural, 1 {1 panel} other {# paneles} }?",
- "delete-dashboards-action-title": "Eliminar { count, plural, 1 {1 panel} other {# paneles} }",
- "delete-dashboards-text": "Ten cuidado, los paneles seleccionados serán eliminados y la información relacionada será irrecuperable.",
- "unassign-dashboard-title": "¿Estás seguro que quieres desasignar el panel '{{dashboardTitle}}'?",
- "unassign-dashboard-text": "Luego de confirmar, el panel será desasignado y no podrá ser accesible por el cliente.",
- "unassign-dashboard": "Desasignar panel",
- "unassign-dashboards-title": "¿Estás seguro que quieres desasignar { count, plural, 1 {1 panel} other {# paneles} }?",
- "unassign-dashboards-text": "Luego de confirmar, los paneles seleccionados serán desasignados y no podrán ser accesibles por el cliente.",
- "public-dashboard-title": "El panel ahora es público",
- "public-dashboard-text": "Tu panel <b>{{dashboardTitle}}</b> es ahora público y podrá ser accedido desde: <a href='{{publicLink}}' target='_blank'>aquí</a>:",
- "public-dashboard-notice": "<b>Nota:</b> No olvides hacer públicos los dispositivos relacionados para acceder a sus datos.",
- "make-private-dashboard-title": "¿Estás seguro que quieres hacer el panel '{{dashboardTitle}}' privado?",
- "make-private-dashboard-text": "Luego de confirmar, el panel será privado y no podrá ser accesible por otros.",
- "make-private-dashboard": "Hacer panel privado",
- "socialshare-text": "'{{dashboardTitle}}' powered by ThingsBoard",
- "socialshare-title": "'{{dashboardTitle}}' powered by ThingsBoard",
+ "unassign-dashboards": "Anular asignación de paneles",
+ "unassign-dashboards-action-title": "Anular asignación { count, plural, 1 {1 dashboard} other {# dashboards} } del cliente",
+ "delete-dashboard-title": "¿Está seguro de que desea eliminar el panel '{{dashboardTitle}}'?",
+ "delete-dashboard-text": "Tener cuidado, después de la confirmación, el panel y todos los datos relacionados se volverán irrecuperables.",
+ "delete-dashboards-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 dashboard} other {# dashboards} }?",
+ "delete-dashboards-action-title": "Eliminar { count, plural, 1 {1 dashboard} other {# dashboards} }",
+ "delete-dashboards-text": "Tener cuidado, después de la confirmación, todos los paneles seleccionados serán eliminados y todos los datos relacionados se volverán irrecuperables.",
+ "unassign-dashboard-title": "¿Está seguro de que desea anular la asignación del panel '{{dashboardTitle}}'?",
+ "unassign-dashboard-text": "Después de la confirmación, se anulará la asignación del panel y no será accesible por el cliente.",
+ "unassign-dashboard": "Anular asignación del panel",
+ "unassign-dashboards-title": "¿Está seguro de que desea anular asignación { count, plural, 1 {1 dashboard} other {# dashboards} }?",
+ "unassign-dashboards-text": "Después de la confirmación, se anulará la asignación de todos los paneles seleccionados y no serán accesibles por el cliente.",
+ "public-dashboard-title": "El panel es ahora público",
+ "public-dashboard-text": "Su panel <b>{{dashboardTitle}}</b> es ahora público y es accesible a través del siguiente enlace público <a href='{{publicLink}}' target='_blank'></a>:",
+ "public-dashboard-notice": "<b>Nota</b> No olvide hacer públicos los dispositivos relacionados para acceder a sus datos.",
+ "make-private-dashboard-title": "¿Está seguro de que desea hacer el panel '{{dashboardTitle}}' privado?",
+ "make-private-dashboard-text": "Después de la confirmación el panel se hará privado y no será accesible por otros.",
+ "make-private-dashboard": "Hacer el panel privado",
+ "socialshare-text": "'{{dashboardTitle}}' desarrollado por ThingsBoard.",
+ "socialshare-title": "'{{dashboardTitle}}' desarrollado por ThingsBoard",
"select-dashboard": "Seleccionar panel",
- "no-dashboards-matching": "Panel '{{entity}}' no encontrado.",
- "dashboard-required": "Panel requerido.",
- "select-existing": "Seleccionar paneles existentes",
+ "no-dashboards-matching": "Paneles que coincidan con '{{entity}}' no fueron encontrados.",
+ "dashboard-required": "Panel es requerido.",
+ "select-existing": "Seleccionar panel existente",
"create-new": "Crear nuevo panel",
- "new-dashboard-title": "Nuevo título",
+ "new-dashboard-title": "Nuevo título de panel",
"open-dashboard": "Abrir panel",
"set-background": "Definir fondo",
"background-color": "Color de fondo",
"background-image": "Imagen de fondo",
- "background-size-mode": "Modo tamaño de fondo",
- "no-image": "No se ha seleccionado ningúna imagen",
- "drop-image": "Suelte una imagen o haga clic para seleccionar un archivo para cargar.",
- "settings": "Ajustes",
- "columns-count": "Número de columnas",
- "columns-count-required": "Número de columnas requerido.",
- "min-columns-count-message": "Solo se permite un número mínimo de 10 columnas.",
- "max-columns-count-message": "Solo se permite un número máximo de 1000 columnas.",
+ "background-size-mode": "Modo de tamaño de fondo",
+ "no-image": "Ninguna imagen seleccionada",
+ "drop-image": "Colocar una imagen o hacer clic para seleccionar un archivo para cargar.",
+ "settings": "Configuración",
+ "columns-count": "Conteo de columnas",
+ "columns-count-required": "Conteo de columnas es requerido.",
+ "min-columns-count-message": "Solamente contar 10 columnas como mínimo es permitido",
+ "max-columns-count-message": "Solamente contar 1000 columnas como máximo es permitiddo",
"widgets-margins": "Margen entre widgets",
"horizontal-margin": "Margen horizontal",
- "horizontal-margin-required": "Margen horizontal requerido.",
- "min-horizontal-margin-message": "Solo se permite margen horizontal mínimo de 0.",
- "max-horizontal-margin-message": "Solo se permite margen horizontal máximo de 50.",
+ "horizontal-margin-required": "El valor del margen horizontal es requerido.",
+ "min-horizontal-margin-message": "Solamente es permitido el 0 como valor mínimo para el margen horizontal",
+ "max-horizontal-margin-message": "Solamente es permitido el 50 como valor máximo para el margen horizontal",
"vertical-margin": "Margen vertical",
- "vertical-margin-required": "Margen vertical requerido.",
- "min-vertical-margin-message": "Solo se permite margen vertical mínimo de 0.",
- "max-vertical-margin-message": "Solo se permite margen vertical máximo de 50.",
+ "vertical-margin-required": "El valor del margen vertical es requerido.",
+ "min-vertical-margin-message": "Solamente es permitido el 0 como valor mínimo para el margen vertical.",
+ "max-vertical-margin-message": "Solamente es permitido el 50 como valor máximo para el margen vertical",
+ "autofill-height": "Llenado automático de altura de diseño",
+ "mobile-layout": "Configuración de diseño para móvil",
+ "mobile-row-height": "Altura de fila para móvil, píxel",
+ "mobile-row-height-required": "Altura de fila para móvil es requerida.",
+ "min-mobile-row-height-message": "Solamente es permitido 5 píxeles como valor mínimo de altura de fila para móvil.",
+ "max-mobile-row-height-message": "Solamente es permitido 200 píxeles como valor máximo de altura de fila para móvil.",
"display-title": "Mostrar título del panel",
+ "toolbar-always-open": "Mantener la barra de herramientas abierta",
"title-color": "Color del título",
- "display-device-selection": "Mostrar selección de dispositivo",
+ "display-dashboards-selection": "Mostrar selección del panel",
+ "display-entities-selection": "Mostrar selección de entidades",
"display-dashboard-timewindow": "Mostrar ventana de tiempo",
"display-dashboard-export": "Mostrar exportar",
"import": "Importar panel",
"export": "Exportar panel",
- "export-failed-error": "Imposible exportar panel: {{error}}",
+ "export-failed-error": "No se puede exportar el panel: {{error}}",
"create-new-dashboard": "Crear nuevo panel",
"dashboard-file": "Archivo del panel",
- "invalid-dashboard-file-error": "Imposible importar panel: Estructura de datos inválida.",
- "dashboard-import-missing-aliases-title": "Configurar alias utilizados por el panel importado",
+ "invalid-dashboard-file-error": "No se puede importar el panel: estructura de datos del panel no es válida.",
+ "dashboard-import-missing-aliases-title": "Configurar los alias utilizados por el panel importado",
"create-new-widget": "Crear nuevo widget",
"import-widget": "Importar widget",
- "widget-file": "Archivo de widget",
- "invalid-widget-file-error": "Imposible importar widget: Estructura de datos inválida.",
- "widget-import-missing-aliases-title": "Configurar alias utilizados por el widget",
- "open-toolbar": "Abrir toolbar del panel",
- "close-toolbar": "Cerrar toolbar",
+ "widget-file": "Archivo del widget",
+ "invalid-widget-file-error": "No se puede importar el widget: estructura de datos del widger no es válida.",
+ "widget-import-missing-aliases-title": "Configurar los alias utilizados por el widget importado",
+ "open-toolbar": "Abrir barra de herramientas del panel",
+ "close-toolbar": "Cerrar barra de herramientas",
"configuration-error": "Error de configuración",
- "alias-resolution-error-title": "Error de configuración de alias del panel",
- "invalid-aliases-config": "No se puede encontrar ningún dispositivo que coincida con algunos de los alias de filtro.<br/>Póngase en contacto con su administrador para resolver este problema.",
+ "alias-resolution-error-title": "Error de configuración de los alias del panel",
+ "invalid-aliases-config": "No se puede encontrar algún dispositivo que coincida con algunos alias del filtro.<br/>Por favor, contacte a su administrador para resolver este problema.",
"select-devices": "Seleccionar dispositivos",
"assignedToCustomer": "Asignado al cliente",
+ "assignedToCustomers": "Asignado a los clientes",
"public": "Público",
- "public-link": "Link público",
- "copy-public-link": "Copiar link público",
- "public-link-copied-message": "El link público del panel se ha copiado al portapapeles"
+ "public-link": "Enlace público",
+ "copy-public-link": "Copiar enlace público",
+ "public-link-copied-message": "El enlace público del panel ha sido copiado al portapapeles",
+ "manage-states": "Gestionar estados del panel",
+ "states": "Estados del panel",
+ "search-states": "Buscar estados del panel",
+ "selected-states": "{ count, plural, 1 {1 dashboard state} other {# dashboard states} } seleccionados",
+ "edit-state": "Editar estado del panel",
+ "delete-state": "Eliminar estado del panel",
+ "add-state": "Agregar estado del panel",
+ "state": "Estado del panel",
+ "state-name": "Nombre",
+ "state-name-required": "El nombre del estado del panel es requerido.",
+ "state-id": "ID del estado",
+ "state-id-required": "ID del estado del panel es requerida.",
+ "state-id-exists": "Ya existe el estado del panel con el mismo ID.",
+ "is-root-state": "Estado raíz",
+ "delete-state-title": "Eliminar estado del panel",
+ "delete-state-text": "¿Está seguro de que desea eliminar el estado del panel con el nombre '{{stateName}}'?",
+ "show-details": "Mostrar detalles",
+ "hide-details": "Ocultar detalles",
+ "select-state": "Seleccionar estado objetivo",
+ "state-controller": "Estado del controlador"
},
"datakey": {
- "settings": "Ajustes",
+ "settings": "Configuración",
"advanced": "Avanzado",
"label": "Etiqueta",
"color": "Color",
+ "units": "Símbolo especial para mostrar al lado del valor",
+ "decimals": "Número de dígitos después del punto flotante",
"data-generation-func": "Función de generación de datos",
- "use-data-post-processing-func": "Usar funcíon de post-procesamiendo de datos",
- "configuration": "Ajustes de clave de datos",
- "timeseries": "Serie de tiempos",
+ "use-data-post-processing-func": "Usar la función de post-procesamiento de datos",
+ "configuration": "Configuración de clave de datos",
+ "timeseries": "Series temporales",
"attributes": "Atributos",
- "timeseries-required": "Series de tiempo del dispositivo requerido.",
- "timeseries-or-attributes-required": "Series de tiempo/Atributos requeridos.",
+ "alarm": "Campos de alarma",
+ "timeseries-required": "Series temporales de la entidad son requeridas",
+ "timeseries-or-attributes-required": "Series temporales/atributos de la entidad son requeridos.",
+ "maximum-timeseries-or-attributes": "Máximo { count, plural, 1 {1 timeseries/attribute is allowed.} other {# timeseries/attributes are allowed} }",
+ "alarm-fields-required": "Campos de alarma son requeridos.",
"function-types": "Tipos de funciones",
- "function-types-required": "Tipos de funciones requerido."
+ "function-types-required": "Tipos de funciones son requeridos.",
+ "maximum-function-types": "Máximo { count, plural, 1 {1 function type is allowed.} other {# function types are allowed} }"
},
"datasource": {
- "type": "Típo de fuente de datos",
- "add-datasource-prompt": "Por favor, agrega una fuente de datos"
+ "type": "Tipo de fuente de datos",
+ "name": "Nombre",
+ "add-datasource-prompt": "Por favor agregue fuente de datos"
},
"details": {
- "edit-mode": "Modo Edición",
- "toggle-edit-mode": "Ir a Modo Edición"
+ "details": "Detalles",
+ "edit-mode": "Modo de edición"
},
"device": {
"device": "Dispositivo",
- "device-required": "Dispositivo requerido.",
+ "device-required": "Dispositivo es requerido.",
"devices": "Dispositivos",
- "management": "Gestión de Dispositivos",
- "view-devices": "Ver dispositivos",
- "device-alias": "Alias de dispositivo",
- "aliases": "Alias de dispositivos",
+ "management": "Gestión del dispositivo",
+ "view-devices": "Ver Dispositivos",
+ "device-alias": "Alias del dispositivo",
+ "aliases": "Alias de los dispositivos",
"no-alias-matching": "'{{alias}}' no encontrado.",
- "no-aliases-found": "Ningún alias encontrado.",
+ "no-aliases-found": "Alias no encontrados.",
"no-key-matching": "'{{key}}' no encontrado.",
- "no-keys-found": "Ninguna clave encontrada.",
- "create-new-alias": "Crear nuevo alias!",
- "create-new-key": "Crear nueva clave!",
- "duplicate-alias-error": "Alias duplicado '{{alias}}'.<br> El alias de los dispositivos deben ser únicos dentro del panel.",
- "configure-alias": "Configurar alias '{{alias}}'",
- "no-devices-matching": "No se encontró dispositivo '{{entity}}'",
+ "no-keys-found": "Claves no encontradas.",
+ "create-new-alias": "Crear uno nuevo!",
+ "create-new-key": "Crear una nueva!",
+ "duplicate-alias-error": "Alias duplicado encontrado '{{alias}}'.<br>Los alias del dispositivo deben ser únicos dentro del panel.",
+ "configure-alias": "Configurar '{{alias}}' alias",
+ "no-devices-matching": "Dispositivos que coincidan con '{{entity}}' no fueron encontrados.",
"alias": "Alias",
- "alias-required": "Alias de dispositivo requerido.",
- "remove-alias": "Eliminar alias",
- "add-alias": "Agregar alias",
- "name-starts-with": "Nombre empieza con",
+ "alias-required": "Alias del dispositivo es requerido.",
+ "remove-alias": "Eliminar alias del dispositivo",
+ "add-alias": "Agregar alias del dispositivo",
+ "name-starts-with": "El nombre del dispositivo comienza con",
"device-list": "Lista de dispositivos",
- "use-device-name-filter": "Usar filtro",
+ "use-device-name-filter": "Utilizar filtro",
"device-list-empty": "Ningún dispositivo seleccionado.",
- "device-name-filter-required": "Nombre de filtro requerido.",
- "device-name-filter-no-device-matched": "Ningún dispositivo encontrado que comience con '{{device}}'.",
- "add": "Agregar dispositivo",
- "assign-to-customer": "Asignar a cliente",
- "assign-device-to-customer": "Asignar dispositivo(s) a Cliente",
- "assign-device-to-customer-text": "Por favor, seleccione los dispositivos que serán asignados al cliente",
- "make-public": "Hacer dispositivo público",
- "make-private": "Hacer dispositivo privado",
- "no-devices-text": "Ningún dispositivo encontrado",
- "assign-to-customer-text": "Por favor, seleccione el cliente para asignar el(los) dispositivo(s)",
+ "device-name-filter-required": "Filtro de nombre de dispositivo es requerido.",
+ "device-name-filter-no-device-matched": "Dispositivos que comienzan con '{{device}}' no fueron encontrados.",
+ "add": "Agregar Dispositivo",
+ "assign-to-customer": "Asignar al cliente",
+ "assign-device-to-customer": "Asignar Dispositivo(s) Al Cliente",
+ "assign-device-to-customer-text": "Por favor seleccionar los dispositivos para asignar al cliente",
+ "make-public": "Hacer público el dispositivo",
+ "make-private": "Hacer privado el dispositivo",
+ "no-devices-text": "Dispositivos no encontrados",
+ "assign-to-customer-text": "Por favor seleccionar el cliente para asignar el(los) dispositivo(s)",
"device-details": "Detalles del dispositivo",
"add-device-text": "Agregar nuevo dispositivo",
"credentials": "Credenciales",
"manage-credentials": "Gestionar credenciales",
"delete": "Eliminar dispositivo",
- "assign-devices": "Asignar dispositivo",
- "assign-devices-text": "Asignar { count, plural, 1 {1 dispositivo} other {# dispositivos} } al cliente",
- "delete-devices": "Eliminar dispositivo",
- "unassign-from-customer": "Desasignar del cliente",
- "unassign-devices": "Desasignar dispositivos",
- "unassign-devices-action-title": "Desasignar { count, plural, 1 {1 dispositivo} other {# dispositivos} } del cliente",
+ "assign-devices": "Asignar dispositivos",
+ "assign-devices-text": "Asignar { count, plural, 1 {1 device} other {# devices} } al cliente",
+ "delete-devices": "Eliminar dispositivos",
+ "unassign-from-customer": "Anular asignación del cliente",
+ "unassign-devices": "Anular asignación de dispositivos",
+ "unassign-devices-action-title": "Anular asignación { count, plural, 1 {1 device} other {# devices} } del cliente",
"assign-new-device": "Asignar nuevo dispositivo",
- "make-public-device-title": "¿Estás seguro que quieres hacer el dispositivo '{{deviceName}}' público?",
- "make-public-device-text": "Luego de confirmar, el dispositivo y la información relacionada serán públicos y podrá ser accesible por otros.",
- "make-private-device-title": "¿Estás seguro que quieres hacer el dispositivo '{{deviceName}}' privado?",
- "make-private-device-text": "Luego de confirmar, el dispositivo y la información relacionada serán privados y no podrá ser accesible por otros.",
+ "make-public-device-title": "¿Está seguro de que desea hacer el dispositivo '{{deviceName}}' público?",
+ "make-public-device-text": "Después de la confirmación, el dispositivo y todos sus datos se harán públicos y accesibles por otros.",
+ "make-private-device-title": "¿Está seguro de que desea hacer el dispositivo '{{deviceName}}' privado?",
+ "make-private-device-text": "Después de la confirmación, el dispositivo y todos sus datos se harán privados y no serán accesibles para otros.",
"view-credentials": "Ver credenciales",
- "delete-device-title": "¿Estás seguro que quieres eliminar el dispositivo '{{deviceName}}'?",
- "delete-device-text": "Ten cuidado, luego de confirmar los dispositivos serán eliminados y la información relacionada será irrecuperable.",
- "delete-devices-title": "¿Estás seguro que quieres eliminar { count, plural, 1 {1 dispositivo} other {# dispositivos} }?",
- "delete-devices-action-title": "Eliminar { count, plural, 1 {1 dispositivo} other {# dispositivos} }",
- "delete-devices-text": "Ten cuidado, luego de confirmar los dispositivos seleccionados serán eliminados y la información relacionada será irrecuperable.",
- "unassign-device-title": "¿Estás seguro que quieres desasignar el dispositivo '{{deviceName}}'?",
- "unassign-device-text": "Luego de confirmar el dispositivo será desasignado y no podrá ser accesible por el cliente.",
- "unassign-device": "Desasignar dispositivo",
- "unassign-devices-title": "¿Estás seguro que quieres desasignar { count, plural, 1 {1 dispositivo} other {# dispositivos} }?",
- "unassign-devices-text": "Luego de confirmar los dispositivos seleccionados serán desasignados y no podrán ser accedidos por el cliente.",
+ "delete-device-title": "¿Está seguro de que desea hacer el dispositivo '{{deviceName}}'?",
+ "delete-device-text": "Tener cuidado, después de la confirmación, el dispositivo y todos sus datos relacionados se volverán irrecuperables.",
+ "delete-devices-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 device} other {# devices} }?",
+ "delete-devices-action-title": "Eliminar { count, plural, 1 {1 device} other {# devices} }",
+ "delete-devices-text": "Tener cuidado, después de la confirmación, todos los dispositivos seleccionados serán eliminados y todos los datos relacionados se volverán irrecuperables.",
+ "unassign-device-title": "¿Está seguro de que desea anular la asignación del dispositivo '{{deviceName}}'?",
+ "unassign-device-text": "Después de la confirmación, se anulará asignación del dispositivo y no será accesible por el cliente.",
+ "unassign-device": "Anular asignación del dispositivo",
+ "unassign-devices-title": "¿Está seguro de que desea anular asignación { count, plural, 1 {1 device} other {# devices} }?",
+ "unassign-devices-text": "Después de la confirmación, se anulará asignación de todos los dispositivos seleccionados y no serán accesibles por el cliente.",
"device-credentials": "Credenciales del dispositivo",
- "credentials-type": "Tipo de credencial",
- "access-token": "Access token",
- "access-token-required": "Access token requerido.",
- "access-token-invalid": "Access token debe tener entre 1 a 20 caracteres.",
+ "credentials-type": "Tipo de credenciales",
+ "access-token": "Token de acceso",
+ "access-token-required": "Token de acceso es requerido.",
+ "access-token-invalid": "La longitud del token de acceso debe ser de 1 a 20 caracteres.",
"rsa-key": "Clave pública RSA",
- "rsa-key-required": "Clave pública RSA requerida.",
- "secret": "Secreta",
- "secret-required": "Secreta requerida.",
+ "rsa-key-required": "Clave pública RSA es requerida.",
+ "secret": "Secreto",
+ "secret-required": "Secreto es requerido.",
+ "device-type": "Tipo de dispositivo",
+ "device-type-required": "Tipo de dispositivo es requerido.",
+ "select-device-type": "Seleccionar tipo de dispositivo",
+ "enter-device-type": "Ingresar tipo de dispositivo",
+ "any-device": "Algún dispositivo",
+ "no-device-types-matching": "Tipos de dispositivos que coincidan con '{{entitySubtype}}' no fueron encontrados.",
+ "device-type-list-empty": "No se seleccionaron tipos de dispositivos.",
+ "device-types": "Tipo de dispositivos",
"name": "Nombre",
- "name-required": "Nombre requerido.",
+ "name-required": "El nombre es requerido.",
"description": "Descripción",
"events": "Eventos",
"details": "Detalles",
- "copyId": "Copiar ID",
- "copyAccessToken": "Copiar access token",
- "idCopiedMessage": "Id del dispositivo copiado al portapapeles",
- "accessTokenCopiedMessage": "Access token del dispositivo copiado al portapapeles",
+ "copyId": "Copiar ID del dispositivo",
+ "copyAccessToken": "Copiar token de acceso",
+ "idCopiedMessage": "ID del dispositivo ha sido copiada al portapapeles",
+ "accessTokenCopiedMessage": "Token de acceso al dispositivo ha sido copiado al portapapeles",
"assignedToCustomer": "Asignado al cliente",
- "unable-delete-device-alias-title": "Imposible eliminar alias del dispositivo",
- "unable-delete-device-alias-text": "Alias '{{deviceAlias}}' no puede ser eliminado. Esta siendo usado por el(los) widget(s):<br/>{{widgetsList}}",
- "is-gateway": "Es gateway",
+ "unable-delete-device-alias-title": "No se puede eliminar el alias del dispositivo",
+ "unable-delete-device-alias-text": "El alias del dispositivo '{{deviceAlias}}' no puede ser eliminado porque es usado por los siguientes widget(s):<br/>{{widgetsList}}",
+ "is-gateway": "Es puerta de entrada",
"public": "Público",
- "device-public": "Dispositivo público"
+ "device-public": "El dispositivo es público",
+ "select-device": "Seleccinar dispositivo"
},
"dialog": {
- "close": "Cerrar cuadro de diálogo"
+ "close": "Cerrar diálogo"
},
"error": {
- "unable-to-connect": "Imposible conectar con el servidor! Por favor, revise su conexión a internet.",
- "unhandled-error-code": "Código de error no manejado: {{errorCode}}",
+ "unable-to-connect": "No se puede conectar al servidor! Por favor revise su conexión a Internet.",
+ "unhandled-error-code": "Código de error no controlado: {{errorCode}}",
"unknown-error": "Error desconocido"
},
"entity": {
- "entity": "Entity",
- "entities": "Entities",
- "aliases": "Entity aliases",
- "entity-alias": "Entity alias",
- "unable-delete-entity-alias-title": "Unable to delete entity alias",
- "unable-delete-entity-alias-text": "Entity alias '{{entityAlias}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}",
- "duplicate-alias-error": "Duplicate alias found '{{alias}}'.<br>Entity aliases must be unique whithin the dashboard.",
- "missing-entity-filter-error": "Filter is missing for alias '{{alias}}'.",
- "configure-alias": "Configure '{{alias}}' alias",
+ "entity": "Entidad",
+ "entities": "Entidades",
+ "aliases": "Alias de las entidades",
+ "entity-alias": "Alias de la entidad",
+ "unable-delete-entity-alias-title": "No se puede borrar alias de la entidad",
+ "unable-delete-entity-alias-text": "Alias de la entidad '{{entityAlias}}' no piuede ser eliminado porque es usado por los siguientes widget(s):<br/>{{widgetsList}}",
+ "duplicate-alias-error": "Alias duplicado fue encontrado '{{alias}}'.<br>Alias de las entidades deben ser únicos dentro del panel.",
+ "missing-entity-filter-error": "Falta filtro para el alias '{{alias}}'.",
+ "configure-alias": "Configurar '{{alias}}' alias",
"alias": "Alias",
- "alias-required": "Entity alias is required.",
- "remove-alias": "Remove entity alias",
- "add-alias": "Add entity alias",
- "entity-list": "Entity list",
- "entity-type": "Entity type",
- "entity-types": "Entity types",
- "entity-type-list": "Entity type list",
- "any-entity": "Any entity",
- "enter-entity-type": "Enter entity type",
- "no-entities-matching": "No entities matching '{{entity}}' were found.",
- "no-entity-types-matching": "No entity types matching '{{entityType}}' were found.",
- "name-starts-with": "Name starts with",
- "use-entity-name-filter": "Use filter",
- "entity-list-empty": "No entities selected.",
- "entity-type-list-empty": "No entity types selected.",
- "entity-name-filter-required": "Entity name filter is required.",
- "entity-name-filter-no-entity-matched": "No entities starting with '{{entity}}' were found.",
- "all-subtypes": "All",
- "select-entities": "Select entities",
- "no-aliases-found": "No aliases found.",
- "no-alias-matching": "'{{alias}}' not found.",
- "create-new-alias": "Create a new one!",
- "key": "Key",
- "key-name": "Key name",
- "no-keys-found": "No keys found.",
- "no-key-matching": "'{{key}}' not found.",
- "create-new-key": "Create a new one!",
- "type": "Type",
- "type-required": "Entity type is required.",
- "type-device": "Device",
- "type-devices": "Devices",
+ "alias-required": "Alias de la entidad es requerida.",
+ "remove-alias": "Eliminar alias de la entidad",
+ "add-alias": "Agregar alias de la entidad",
+ "entity-list": "Lista de entidades",
+ "entity-type": "Tipo de entidad",
+ "entity-types": "Tipos de entidades",
+ "entity-type-list": "Lista de tipos de entidades",
+ "any-entity": "Alguna entidad",
+ "enter-entity-type": "Ingresara tipo de entidad",
+ "no-entities-matching": "Entidades que coincidan con '{{entity}}' no fueron encontradas.",
+ "no-entity-types-matching": "Tipos de entidades que coincidan con '{{entityType}}' no fueron encontrados.",
+ "name-starts-with": "El nombre comienza con",
+ "use-entity-name-filter": "Utilizar filtro",
+ "entity-list-empty": "Entidades no seleccionadas.",
+ "entity-type-list-empty": "Tipos de entidades no seleccionados.",
+ "entity-name-filter-required": "Filtro del nombre de la entidad es requerido.",
+ "entity-name-filter-no-entity-matched": "Entidades que comienzan con '{{entity}}' no fueron encontradas.",
+ "all-subtypes": "Todas",
+ "select-entities": "Seleccionar entidades",
+ "no-aliases-found": "Alias no encontrados.",
+ "no-alias-matching": "'{{alias}}' no encontrado.",
+ "create-new-alias": "Crear uno nuevo!",
+ "key": "Clave",
+ "key-name": "Nombre de clave",
+ "no-keys-found": "Claves no encontradas.",
+ "no-key-matching": "'{{key}}' no encontrada.",
+ "create-new-key": "Crear una nueva!",
+ "type": "Tipo",
+ "type-required": "Tipo de entidad es requerido.",
+ "type-device": "Dispositivo",
+ "type-devices": "Dispositivos",
"list-of-devices": "{ count, plural, 1 {One device} other {List of # devices} }",
- "device-name-starts-with": "Devices whose names start with '{{prefix}}'",
- "type-asset": "Asset",
- "type-assets": "Assets",
+ "device-name-starts-with": "Dispositivos cuyos nombres comienzan con '{{prefix}}'",
+ "type-asset": "Activo",
+ "type-assets": "Activos",
"list-of-assets": "{ count, plural, 1 {One asset} other {List of # assets} }",
- "asset-name-starts-with": "Assets whose names start with '{{prefix}}'",
- "type-rule": "Rule",
- "type-rules": "Rules",
+ "asset-name-starts-with": "Activos cuyos nombres comienzan con '{{prefix}}'",
+ "type-entity-view": "Entity View",
+ "type-entity-views": "Entity Views",
+ "list-of-entity-views": "{ count, plural, 1 {One entity view} other {List of # entity views} }",
+ "entity-view-name-starts-with": "Entity Views whose names start with '{{prefix}}'",
+ "type-rule": "Regla",
+ "type-rules": "Reglas",
"list-of-rules": "{ count, plural, 1 {One rule} other {List of # rules} }",
- "rule-name-starts-with": "Rules whose names start with '{{prefix}}'",
- "type-plugin": "Plugin",
- "type-plugins": "Plugins",
+ "rule-name-starts-with": "Reglas cuyos nombres comienzan con '{{prefix}}'",
+ "type-plugin": "Complemento",
+ "type-plugins": "Complementos",
"list-of-plugins": "{ count, plural, 1 {One plugin} other {List of # plugins} }",
- "plugin-name-starts-with": "Plugins whose names start with '{{prefix}}'",
- "type-tenant": "Tenant",
- "type-tenants": "Tenants",
+ "plugin-name-starts-with": "Complementos cuyos nombres comienzan con '{{prefix}}'",
+ "type-tenant": "Organización",
+ "type-tenants": "Organizaciones",
"list-of-tenants": "{ count, plural, 1 {One tenant} other {List of # tenants} }",
- "tenant-name-starts-with": "Tenants whose names start with '{{prefix}}'",
- "type-customer": "Customer",
- "type-customers": "Customers",
+ "tenant-name-starts-with": "Organizaciones cuyos nombres comienzan con '{{prefix}}'",
+ "type-customer": "Cliente",
+ "type-customers": "Clientes",
"list-of-customers": "{ count, plural, 1 {One customer} other {List of # customers} }",
- "customer-name-starts-with": "Customers whose names start with '{{prefix}}'",
- "type-user": "User",
- "type-users": "Users",
+ "customer-name-starts-with": "Clientes cuyos nombres comienzan con '{{prefix}}'",
+ "type-user": "Usuario",
+ "type-users": "Usuarios",
"list-of-users": "{ count, plural, 1 {One user} other {List of # users} }",
- "user-name-starts-with": "Users whose names start with '{{prefix}}'",
- "type-dashboard": "Dashboard",
- "type-dashboards": "Dashboards",
+ "user-name-starts-with": "Usuarios cuyos nombres comienzan con '{{prefix}}'",
+ "type-dashboard": "Panel",
+ "type-dashboards": "Paneles",
"list-of-dashboards": "{ count, plural, 1 {One dashboard} other {List of # dashboards} }",
- "dashboard-name-starts-with": "Dashboards whose names start with '{{prefix}}'",
- "type-alarm": "Alarm",
- "type-alarms": "Alarms",
+ "dashboard-name-starts-with": "Paneles cuyos nombres comienzan con '{{prefix}}'",
+ "type-alarm": "Alarma",
+ "type-alarms": "Alarmas",
"list-of-alarms": "{ count, plural, 1 {One alarms} other {List of # alarms} }",
- "alarm-name-starts-with": "Alarms whose names start with '{{prefix}}'",
- "type-rulechain": "Rule chain",
- "type-rulechains": "Rule chains",
+ "alarm-name-starts-with": "Alarmas cuyos nombres comienzan con '{{prefix}}'",
+ "type-rulechain": "Cadena de reglas",
+ "type-rulechains": "Cadenas de reglas",
"list-of-rulechains": "{ count, plural, 1 {One rule chain} other {List of # rule chains} }",
- "rulechain-name-starts-with": "Rule chains whose names start with '{{prefix}}'",
- "type-current-customer": "Current Customer",
- "search": "Search entities",
- "selected-entities": "{ count, plural, 1 {1 entity} other {# entities} } selected",
- "entity-name": "Entity name",
- "details": "Entity details",
- "no-entities-prompt": "No entities found",
- "no-data": "No data to display"
+ "rulechain-name-starts-with": "Cadenas reglas cuyos nombres comienzan con '{{prefix}}'",
+ "type-rulenode": "Nodo de reglas",
+ "type-rulenodes": "Nodos de reglas",
+ "list-of-rulenodes": "{ count, plural, 1 {One rule node} other {List of # rule nodes} }",
+ "rulenode-name-starts-with": "Nodos de reglas cuyos nombres comienzan con '{{prefix}}'",
+ "type-current-customer": "Cliente Actual",
+ "search": "Buscar entidades",
+ "selected-entities": "{ count, plural, 1 {1 entity} other {# entities} } seleccionadas",
+ "entity-name": "Nombre de la entidad",
+ "details": "Detalles de la entidad",
+ "no-entities-prompt": "Entidades no encontradas",
+ "no-data": "No hay datos para mostrar",
+ "columns-to-display": "Columns to Display"
+ },
+ "entity-view": {
+ "entity-view": "Entity View",
+ "entity-views": "Entity Views",
+ "management": "Entity View management",
+ "view-entity-views": "View Entity Views",
+ "entity-view-alias": "Entity View alias",
+ "aliases": "Entity View aliases",
+ "no-alias-matching": "'{{alias}}' not found.",
+ "no-aliases-found": "No aliases found.",
+ "no-key-matching": "'{{key}}' not found.",
+ "no-keys-found": "No keys found.",
+ "create-new-alias": "Create a new one!",
+ "create-new-key": "Create a new one!",
+ "duplicate-alias-error": "Duplicate alias found '{{alias}}'.<br>Entity View aliases must be unique whithin the dashboard.",
+ "configure-alias": "Configure '{{alias}}' alias",
+ "no-entity-views-matching": "No entity views matching '{{entity}}' were found.",
+ "alias": "Alias",
+ "alias-required": "Entity View alias is required.",
+ "remove-alias": "Remove entity view alias",
+ "add-alias": "Add entity view alias",
+ "name-starts-with": "Entity View name starts with",
+ "entity-view-list": "Entity View list",
+ "use-entity-view-name-filter": "Use filter",
+ "entity-view-list-empty": "No entity views selected.",
+ "entity-view-name-filter-required": "Entity view name filter is required.",
+ "entity-view-name-filter-no-entity-view-matched": "No entity views starting with '{{entityView}}' were found.",
+ "add": "Add Entity View",
+ "assign-to-customer": "Assign to customer",
+ "assign-entity-view-to-customer": "Assign Entity View(s) To Customer",
+ "assign-entity-view-to-customer-text": "Please select the entity views to assign to the customer",
+ "no-entity-views-text": "No entity views found",
+ "assign-to-customer-text": "Please select the customer to assign the entity view(s)",
+ "entity-view-details": "Entity view details",
+ "add-entity-view-text": "Add new entity view",
+ "delete": "Delete entity view",
+ "assign-entity-views": "Assign entity views",
+ "assign-entity-views-text": "Assign { count, plural, 1 {1 entityView} other {# entityViews} } to customer",
+ "delete-entity-views": "Delete entity views",
+ "unassign-from-customer": "Unassign from customer",
+ "unassign-entity-views": "Unassign entity views",
+ "unassign-entity-views-action-title": "Unassign { count, plural, 1 {1 entityView} other {# entityViews} } from customer",
+ "assign-new-entity-view": "Assign new entity view",
+ "delete-entity-view-title": "Are you sure you want to delete the entity view '{{entityViewName}}'?",
+ "delete-entity-view-text": "Be careful, after the confirmation the entity view and all related data will become unrecoverable.",
+ "delete-entity-views-title": "Are you sure you want to entity view { count, plural, 1 {1 entityView} other {# entityViews} }?",
+ "delete-entity-views-action-title": "Delete { count, plural, 1 {1 entityView} other {# entityViews} }",
+ "delete-entity-views-text": "Be careful, after the confirmation all selected entity views will be removed and all related data will become unrecoverable.",
+ "unassign-entity-view-title": "Are you sure you want to unassign the entity view '{{entityViewName}}'?",
+ "unassign-entity-view-text": "After the confirmation the entity view will be unassigned and won't be accessible by the customer.",
+ "unassign-entity-view": "Unassign entity view",
+ "unassign-entity-views-title": "Are you sure you want to unassign { count, plural, 1 {1 entityView} other {# entityViews} }?",
+ "unassign-entity-views-text": "After the confirmation all selected entity views will be unassigned and won't be accessible by the customer.",
+ "entity-view-type": "Entity View type",
+ "entity-view-type-required": "Entity View type is required.",
+ "select-entity-view-type": "Select entity view type",
+ "enter-entity-view-type": "Enter entity view type",
+ "any-entity-view": "Any entity view",
+ "no-entity-view-types-matching": "No entity view types matching '{{entitySubtype}}' were found.",
+ "entity-view-type-list-empty": "No entity view types selected.",
+ "entity-view-types": "Entity View types",
+ "name": "Name",
+ "name-required": "Name is required.",
+ "description": "Description",
+ "events": "Events",
+ "details": "Details",
+ "copyId": "Copy entity view Id",
+ "assignedToCustomer": "Assigned to customer",
+ "unable-entity-view-device-alias-title": "Unable to delete entity view alias",
+ "unable-entity-view-device-alias-text": "Device alias '{{entityViewAlias}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}",
+ "select-entity-view": "Select entity view",
+ "make-public": "Make entity view public",
+ "start-ts": "Start time",
+ "end-ts": "End time",
+ "date-limits": "Date limits",
+ "client-attributes": "Client attributes",
+ "shared-attributes": "Shared attributes",
+ "server-attributes": "Server attributes",
+ "latest-timeseries": "Latest timeseries"
},
"event": {
"event-type": "Tipo de evento",
"type-error": "Error",
- "type-lc-event": "Ciclo de vida",
+ "type-lc-event": "Ciclo de vida del evento",
"type-stats": "Estadísticas",
- "no-events-prompt": "Ningún evento encontrado.",
+ "type-debug-rule-node": "Depurar",
+ "type-debug-rule-chain": "Depurar",
+ "no-events-prompt": "Eventos no encontrados",
"error": "Error",
"alarm": "Alarma",
- "event-time": "Hora del evento",
+ "event-time": "Tiempo del evento",
"server": "Servidor",
"body": "Cuerpo",
"method": "Método",
+ "type": "Tipo",
+ "entity": "Entidad",
+ "message-id": "ID del mensaje",
+ "message-type": "Tipo de mensaje",
+ "data-type": "Tipo de datos",
+ "relation-type": "Tipo de relación",
+ "metadata": "Metadatos",
+ "data": "Datos",
"event": "Evento",
- "status": "Status",
+ "status": "Estado",
"success": "Éxito",
- "failed": "Fallo",
+ "failed": "Falla",
"messages-processed": "Mensajes procesados",
- "errors-occurred": "Ocurrieron errores"
+ "errors-occurred": "Errores ocurridos"
},
"extension": {
- "extensions": "Extensions",
- "selected-extensions": "{ count, plural, 1 {1 extension} other {# extensions} } selected",
- "type": "Type",
- "key": "Key",
- "value": "Value",
- "id": "Id",
- "extension-id": "Extension id",
- "extension-type": "Extension type",
+ "extensions": "Extensiones",
+ "selected-extensions": "{ count, plural, 1 {1 extension} other {# extensions} } seleccionadas",
+ "type": "Tipo",
+ "key": "Clave",
+ "value": "Valor",
+ "id": "ID",
+ "extension-id": "ID de extensión",
+ "extension-type": "Tipo de extensión",
"transformer-json": "JSON *",
- "unique-id-required": "Current extension id already exists.",
- "delete": "Delete extension",
- "add": "Add extension",
- "edit": "Edit extension",
- "delete-extension-title": "Are you sure you want to delete the extension '{{extensionId}}'?",
- "delete-extension-text": "Be careful, after the confirmation the extension and all related data will become unrecoverable.",
- "delete-extensions-title": "Are you sure you want to delete { count, plural, 1 {1 extension} other {# extensions} }?",
- "delete-extensions-text": "Be careful, after the confirmation all selected extensions will be removed.",
- "converters": "Converters",
- "converter-id": "Converter id",
- "configuration": "Configuration",
- "converter-configurations": "Converter configurations",
- "token": "Security token",
- "add-converter": "Add converter",
- "add-config": "Add converter configuration",
- "device-name-expression": "Device name expression",
- "device-type-expression": "Device type expression",
- "custom": "Custom",
- "to-double": "To Double",
- "transformer": "Transformer",
- "json-required": "Transformer json is required.",
- "json-parse": "Unable to parse transformer json.",
- "attributes": "Attributes",
- "add-attribute": "Add attribute",
- "add-map": "Add mapping element",
- "timeseries": "Timeseries",
- "add-timeseries": "Add timeseries",
- "field-required": "Field is required",
- "brokers": "Brokers",
- "add-broker": "Add broker",
+ "unique-id-required": "Ya existe ID de extensión actual.",
+ "delete": "Eliminar extensión",
+ "add": "Agregar extensión",
+ "edit": "Editar extensión",
+ "delete-extension-title": "¿Está seguro de que desea eliminar la extensión '{{extensionId}}'?",
+ "delete-extension-text": "Tener cuidado, después de la confirmación, la extensión y todos los datos relacionados se volverán irrecuperables.",
+ "delete-extensions-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 extension} other {# extensions} }?",
+ "delete-extensions-text": "Tener cuidado, después de la confirmación, se eliminarán todas las extensiones seleccionadas.",
+ "converters": "Conversores",
+ "converter-id": "ID del conversor",
+ "configuration": "Configuración",
+ "converter-configurations": "Configuraciones del conversor",
+ "token": "Token de seguridad",
+ "add-converter": "Agregar conversor",
+ "add-config": "Configuración para agregar conversor",
+ "device-name-expression": "Expresión del nombre del dispositivo",
+ "device-type-expression": "Expresión del tipo del dispositivo",
+ "custom": "Personalizado",
+ "to-double": "Para duplicar",
+ "transformer": "Transformador",
+ "json-required": "Transformador json es requerido.",
+ "json-parse": "No se puede analizar el transformador json.",
+ "attributes": "Atributos",
+ "add-attribute": "Agregar atributos",
+ "add-map": "Agregar elemento de mapeo",
+ "timeseries": "Series temporales",
+ "add-timeseries": "Agregar series temporales",
+ "field-required": "Campo es requerido",
+ "brokers": "Agentes",
+ "add-broker": "Agregar agente",
"host": "Host",
- "port": "Port",
- "port-range": "Port should be in a range from 1 to 65535.",
- "ssl": "Ssl",
- "credentials": "Credentials",
- "username": "Username",
- "password": "Password",
- "retry-interval": "Retry interval in milliseconds",
- "anonymous": "Anonymous",
- "basic": "Basic",
+ "port": "Puerto",
+ "port-range": "El puerto debe estar en un rango desde 1 hasta 65535.",
+ "ssl": "SSL",
+ "credentials": "Credenciales",
+ "username": "Nombre de usuario",
+ "password": "Contraseña",
+ "retry-interval": "Intervalo de reintento en milisegundos",
+ "anonymous": "Anónimo",
+ "basic": "Básico",
"pem": "PEM",
- "ca-cert": "CA certificate file *",
- "private-key": "Private key file *",
- "cert": "Certificate file *",
- "no-file": "No file selected.",
- "drop-file": "Drop a file or click to select a file to upload.",
- "mapping": "Mapping",
- "topic-filter": "Topic filter",
- "converter-type": "Converter type",
+ "ca-cert": "Archivo de certificado CA *",
+ "private-key": "Archivo de clave privado *",
+ "cert": "Archivo de certificado *",
+ "no-file": "Ningún archivo seleccionado.",
+ "drop-file": "Colocar un archivo o hacer clic para seleccionar un archivo para cargar.",
+ "mapping": "Mapeo",
+ "topic-filter": "Filtro de tema",
+ "converter-type": "Tipo de conversor",
"converter-json": "Json",
- "json-name-expression": "Device name json expression",
- "topic-name-expression": "Device name topic expression",
- "json-type-expression": "Device type json expression",
- "topic-type-expression": "Device type topic expression",
- "attribute-key-expression": "Attribute key expression",
- "attr-json-key-expression": "Attribute key json expression",
- "attr-topic-key-expression": "Attribute key topic expression",
- "request-id-expression": "Request id expression",
- "request-id-json-expression": "Request id json expression",
- "request-id-topic-expression": "Request id topic expression",
- "response-topic-expression": "Response topic expression",
- "value-expression": "Value expression",
- "topic": "Topic",
- "timeout": "Timeout in milliseconds",
- "converter-json-required": "Converter json is required.",
- "converter-json-parse": "Unable to parse converter json.",
- "filter-expression": "Filter expression",
- "connect-requests": "Connect requests",
- "add-connect-request": "Add connect request",
- "disconnect-requests": "Disconnect requests",
- "add-disconnect-request": "Add disconnect request",
- "attribute-requests": "Attribute requests",
- "add-attribute-request": "Add attribute request",
- "attribute-updates": "Attribute updates",
- "add-attribute-update": "Add attribute update",
- "server-side-rpc": "Server side RPC",
- "add-server-side-rpc-request": "Add server-side RPC request",
- "device-name-filter": "Device name filter",
- "attribute-filter": "Attribute filter",
- "method-filter": "Method filter",
- "request-topic-expression": "Request topic expression",
- "response-timeout": "Response timeout in milliseconds",
- "topic-expression": "Topic expression",
- "client-scope": "Client scope",
- "add-device": "Add device",
- "opc-server": "Servers",
- "opc-add-server": "Add server",
- "opc-add-server-prompt": "Please add server",
- "opc-application-name": "Application name",
- "opc-application-uri": "Application uri",
- "opc-scan-period-in-seconds": "Scan period in seconds",
- "opc-security": "Security",
- "opc-identity": "Identity",
- "opc-keystore": "Keystore",
- "opc-type": "Type",
- "opc-keystore-type": "Type",
- "opc-keystore-location": "Location *",
- "opc-keystore-password": "Password",
+ "json-name-expression": "Expresión json para nombre del dispositivo",
+ "topic-name-expression": "Expresión temática para nombre del dispositivo",
+ "json-type-expression": "Expresión json para tipo de dispositivo",
+ "topic-type-expression": "Expresión temática para tipo de dispositivo",
+ "attribute-key-expression": "Expresión para clave de atributo",
+ "attr-json-key-expression": "Expresión json para clave de atributo",
+ "attr-topic-key-expression": "Expresión temática para clave de atributo",
+ "request-id-expression": "Expresión para solicitud de ID",
+ "request-id-json-expression": "Expresión json para solicitud de ID",
+ "request-id-topic-expression": "Expresión temática para solicitud de ID",
+ "response-topic-expression": "Expresión temática para respuesta",
+ "value-expression": "Expresión para valor",
+ "topic": "Tema",
+ "timeout": "Tiempo de espera en milisegundos",
+ "converter-json-required": "Conversor json es requerido.",
+ "converter-json-parse": "No se puede analizar el conversor json.",
+ "filter-expression": "Expresión para filtro",
+ "connect-requests": "Solicitudes de conexión",
+ "add-connect-request": "Agregar solicitudes de conexión",
+ "disconnect-requests": "Solicitudes de desconexión",
+ "add-disconnect-request": "Agregar solicitudes de desconexión",
+ "attribute-requests": "Solicitudes de atributo",
+ "add-attribute-request": "Agregar solicitudes de atributo",
+ "attribute-updates": "Actualizaciones de atributo",
+ "add-attribute-update": "Agregar actualizaciones de atributo",
+ "server-side-rpc": "RPC lado servidor",
+ "add-server-side-rpc-request": "Agregar solicitud RPC lado servidor",
+ "device-name-filter": "Filtro de nombre de dispositivo",
+ "attribute-filter": "Filtro de atributo",
+ "method-filter": "Filtro de método",
+ "request-topic-expression": "Expresión temática para solicitud",
+ "response-timeout": "Respuesta a tiempo de espera en milisegundos",
+ "topic-expression": "Expresión temática",
+ "client-scope": "Alcance del cliente",
+ "add-device": "Agregar dispositivo",
+ "opc-server": "Servidores",
+ "opc-add-server": "Agregar servidor",
+ "opc-add-server-prompt": "Por favor agregar servidor",
+ "opc-application-name": "Nombre de aplicación",
+ "opc-application-uri": "Aplicación URI",
+ "opc-scan-period-in-seconds": "Período de exploración en segundos",
+ "opc-security": "Seguridad",
+ "opc-identity": "Identidad",
+ "opc-keystore": "Repositorio",
+ "opc-type": "Tipo",
+ "opc-keystore-type": "Tipo",
+ "opc-keystore-location": "Ubicación *",
+ "opc-keystore-password": "Contraseña",
"opc-keystore-alias": "Alias",
- "opc-keystore-key-password": "Key password",
- "opc-device-node-pattern": "Device node pattern",
- "opc-device-name-pattern": "Device name pattern",
- "modbus-server": "Servers/slaves",
- "modbus-add-server": "Add server/slave",
- "modbus-add-server-prompt": "Please add server/slave",
- "modbus-transport": "Transport",
- "modbus-port-name": "Serial port name",
- "modbus-encoding": "Encoding",
- "modbus-parity": "Parity",
- "modbus-baudrate": "Baud rate",
- "modbus-databits": "Data bits",
- "modbus-stopbits": "Stop bits",
- "modbus-databits-range": "Data bits should be in a range from 7 to 8.",
- "modbus-stopbits-range": "Stop bits should be in a range from 1 to 2.",
- "modbus-unit-id": "Unit ID",
- "modbus-unit-id-range": "Unit ID should be in a range from 1 to 247.",
- "modbus-device-name": "Device name",
- "modbus-poll-period": "Poll period (ms)",
- "modbus-attributes-poll-period": "Attributes poll period (ms)",
- "modbus-timeseries-poll-period": "Timeseries poll period (ms)",
- "modbus-poll-period-range": "Poll period should be positive value.",
- "modbus-tag": "Tag",
- "modbus-function": "Function",
- "modbus-register-address": "Register address",
- "modbus-register-address-range": "Register address should be in a range from 0 to 65535.",
- "modbus-register-bit-index": "Bit index",
- "modbus-register-bit-index-range": "Bit index should be in a range from 0 to 15.",
- "modbus-register-count": "Register count",
- "modbus-register-count-range": "Register count should be a positive value.",
- "modbus-byte-order": "Byte order",
+ "opc-keystore-key-password": "Clave de contraseña",
+ "opc-device-node-pattern": "Patrón de nodo de dispostivo",
+ "opc-device-name-pattern": "Patrón de nombre de dispositivo",
+ "modbus-server": "Servidores/esclavos",
+ "modbus-add-server": "Agregar servidor/esclavo",
+ "modbus-add-server-prompt": "Por favor agregar servidor/esclavo",
+ "modbus-transport": "Transporte",
+ "modbus-port-name": "Nombre del puerto serial",
+ "modbus-encoding": "Codificación",
+ "modbus-parity": "Paridad",
+ "modbus-baudrate": "Tasa de baudios",
+ "modbus-databits": "Bits de datos",
+ "modbus-stopbits": "Bits de parada",
+ "modbus-databits-range": "Bits de datos deben estar en un rango entre 7 y 8.",
+ "modbus-stopbits-range": "Bits de parada deben estar en un rango entre 1 a 2.",
+ "modbus-unit-id": "ID de unidad",
+ "modbus-unit-id-range": "ID de unidad debe estar en un rango entre 1 a 247.",
+ "modbus-device-name": "Nombre del dispositivo",
+ "modbus-poll-period": "Período de sondeo (ms)",
+ "modbus-attributes-poll-period": "Atributos del período de sondeo (ms)",
+ "modbus-timeseries-poll-period": "Período de sondeo de las series temporales (ms)",
+ "modbus-poll-period-range": "El período de sondeo debe ser una valor positivo.",
+ "modbus-tag": "Etiqueta",
+ "modbus-function": "Función",
+ "modbus-register-address": "Dirección del registro",
+ "modbus-register-address-range": "Dirección del registro debe estar en un rango entre 0 y 65535.",
+ "modbus-register-bit-index": "Índice de bit",
+ "modbus-register-bit-index-range": "Índice de bit debe estar en un rango entre 0 y 15.",
+ "modbus-register-count": "Contador del registro",
+ "modbus-register-count-range": "Contador del registro debe ser un valor positivo.",
+ "modbus-byte-order": "Orden del byte",
"sync": {
- "status": "Status",
- "sync": "Sync",
- "not-sync": "Not sync",
- "last-sync-time": "Last sync time",
- "not-available": "Not available"
+ "status": "Estado",
+ "sync": "Sincronización",
+ "not-sync": "No sincronización",
+ "last-sync-time": "Último tiempo de sincroniación",
+ "not-available": "No disponible"
},
- "export-extensions-configuration": "Export extensions configuration",
- "import-extensions-configuration": "Import extensions configuration",
- "import-extensions": "Import extensions",
- "import-extension": "Import extension",
- "export-extension": "Export extension",
- "file": "Extensions file",
- "invalid-file-error": "Invalid extension file"
+ "export-extensions-configuration": "Exportar configuración de extensiones",
+ "import-extensions-configuration": "Importar configuración de extensiones",
+ "import-extensions": "Importar extensiones",
+ "import-extension": "Importar extensión",
+ "export-extension": "Exportar extensión",
+ "file": "Archivo de extensiones",
+ "invalid-file-error": "Archivo de extensión no válido"
},
"fullscreen": {
- "expand": "Expandir a Pantalla Completa",
- "exit": "Salir de Pantalla Completa",
- "toggle": "Cambiar el modo de Pantalla Completa",
- "fullscreen": "Pantalla Completa"
+ "expand": "Expandir a pantalla completa",
+ "exit": "Salir de pantalla completa",
+ "toggle": "Alternar el modo de pantalla completa",
+ "fullscreen": "Pantalla completa"
},
"function": {
"function": "Función"
},
"grid": {
- "delete-item-title": "¿Estás seguro que quieres eliminar este item?",
- "delete-item-text": "Ten cuidado, luego de confirmar el item será eliminado y la información relacionada será irrecuperable.",
- "delete-items-title": "¿Estás seguro que quieres eliminar { count, plural, 1 {1 item} other {# items} }?",
+ "delete-item-title": "¿Está seguro de que desea eliminar este ítem?",
+ "delete-item-text": "Tener cuidado, después de la confirmación, este ítem y todos los datos relacionados se volverán irrecuperables.",
+ "delete-items-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 item} other {# items} }?",
"delete-items-action-title": "Eliminar { count, plural, 1 {1 item} other {# items} }",
- "delete-items-text": "Ten cuidado, luego de confirmar los items seleccionados serán eliminados y la información relacionada será irrecuperable.",
- "add-item-text": "Agregar nuevo item",
- "no-items-text": "Ningún item encontrado",
- "item-details": "Detalles del item",
- "delete-item": "Borrar Item",
- "delete-items": "Borrar Items",
- "scroll-to-top": "Ir hacia arriba"
+ "delete-items-text": "Tener cuidado, después de la confirmación se eliminarán todos los ítems seleccionados y todos los datos relacionados se volverán irrecuperables.",
+ "add-item-text": "Agregar nuevo ítem",
+ "no-items-text": "Ítems no encontrados",
+ "item-details": "Detalles del ítem",
+ "delete-item": "Eliminar ítem",
+ "delete-items": "Eliminar ítems",
+ "scroll-to-top": "Desplazar al inicio"
},
"help": {
- "goto-help-page": "Ir a Página de Ayuda"
+ "goto-help-page": "Ir a la página de ayuda"
},
"home": {
- "home": "Principal",
+ "home": "Página principal",
"profile": "Perfil",
- "logout": "Salir",
- "menu": "Menu",
+ "logout": "Cerrar sesión",
+ "menu": "Menú",
"avatar": "Avatar",
"open-user-menu": "Abrir menú de usuario"
},
"import": {
"no-file": "Ningún archivo seleccionado",
- "drop-file": "Arrastra un archivo JSON o clickea para seleccionar uno."
+ "drop-file": "Colocar un archivo JSON o hacer clic para seleccionar un archivo para cargar."
},
"item": {
"selected": "Seleccionado"
},
"js-func": {
- "no-return-error": "La función debe retornar un valor!",
- "return-type-mismatch": "La función debe retornar un valor de tipo: '{{type}}'!"
+ "no-return-error": "La función debe devolver el valor!",
+ "return-type-mismatch": "La función debe devolver el valor de '{{type}}' type!",
+ "tidy": "Ordenado"
},
"key-val": {
- "key": "Key",
- "value": "Value",
- "remove-entry": "Remove entry",
- "add-entry": "Add entry",
- "no-data": "No entries"
+ "key": "Clave",
+ "value": "Valor",
+ "remove-entry": "Eliminar entrada",
+ "add-entry": "Agregar entrada",
+ "no-data": "Ninguna entrada"
},
"layout": {
- "layout": "Layout",
- "manage": "Manage layouts",
- "settings": "Layout settings",
+ "layout": "Diseño",
+ "manage": "Gestionar diseños",
+ "settings": "Configuaración de diseño",
"color": "Color",
- "main": "Main",
- "right": "Right",
- "select": "Select target layout"
+ "main": "Principal",
+ "right": "Derecha",
+ "select": "Seleccionar diseño objetivo"
},
"legend": {
- "position": "Posición de leyenda",
- "show-max": "Mostrar máximo",
- "show-min": "Mostrar mínimo",
- "show-avg": "Mostrar promedio",
- "show-total": "Mostrar total",
- "settings": "Ajustes de leyenda.",
- "min": "min",
- "max": "max",
- "avg": "prom",
+ "position": "Posición de la leyenda",
+ "show-max": "Mostrar valor máximo",
+ "show-min": "Mostrar valor mínimo",
+ "show-avg": "Mostrar valor promedio",
+ "show-total": "Mostrar valor total",
+ "settings": "Configuración de la leyenda",
+ "min": "mínimo",
+ "max": "máximo",
+ "avg": "promedio",
"total": "total"
},
"login": {
- "login": "Ingresar",
- "request-password-reset": "Pedir restablecer contraseña",
- "reset-password": "Restablecer contraseña",
- "create-password": "Crear contraseña",
- "passwords-mismatch-error": "Las contraseñas deben ser las mismas!",
- "password-again": "Reingresa la contraseña",
- "sign-in": "Iniciar sesión",
- "username": "Usuario (email)",
- "remember-me": "Recordar",
- "forgot-password": "¿Olvidaste tu contraseña?",
- "password-reset": "Restablecer Contraseña",
+ "login": "Iniciar sesión",
+ "request-password-reset": "Solicitar Restablecimiento Contraseña",
+ "reset-password": "Restablecer Contraseña",
+ "create-password": "Crear Contraseña",
+ "passwords-mismatch-error": "Las contraseñas introducidas deben ser las mismas!",
+ "password-again": "Contraseña nuevamente",
+ "sign-in": "Por favor registrarse",
+ "username": "Nombre de usuario (correo electrónico)",
+ "remember-me": "Recordarme",
+ "forgot-password": "Olvidó Contraseña?",
+ "password-reset": "Restablecimiento de Contraseña",
"new-password": "Nueva contraseña",
- "new-password-again": "Repita la nueva contraseña",
- "password-link-sent-message": "Se ha enviado el enlace de restablecimiento de contraseña con éxito!",
- "email": "Email"
+ "new-password-again": "Nueva contraseña otra vez",
+ "password-link-sent-message": "El enlace para el restablecimieneto de la contraseña fue enviado exitosamente!",
+ "email": "Correo electrónico"
},
"position": {
- "top": "Arriba",
- "bottom": "Abajo",
+ "top": "Superior",
+ "bottom": "Inferior",
"left": "Izquierda",
"right": "Derecha"
},
@@ -946,163 +1129,179 @@
"current-password": "Contraseña actual"
},
"relation": {
- "relations": "Relations",
- "direction": "Direction",
+ "relations": "Relaciones",
+ "direction": "Dirección",
"search-direction": {
- "FROM": "From",
- "TO": "To"
+ "FROM": "Desde",
+ "TO": "Hacia"
},
"direction-type": {
- "FROM": "from",
- "TO": "to"
+ "FROM": "desde",
+ "TO": "hacia"
},
- "from-relations": "Outbound relations",
- "to-relations": "Inbound relations",
- "selected-relations": "{ count, plural, 1 {1 relation} other {# relations} } selected",
- "type": "Type",
- "to-entity-type": "To entity type",
- "to-entity-name": "To entity name",
- "from-entity-type": "From entity type",
- "from-entity-name": "From entity name",
- "to-entity": "To entity",
- "from-entity": "From entity",
- "delete": "Delete relation",
- "relation-type": "Relation type",
- "relation-type-required": "Relation type is required.",
- "any-relation-type": "Any type",
- "add": "Add relation",
- "edit": "Edit relation",
- "delete-to-relation-title": "Are you sure you want to delete relation to the entity '{{entityName}}'?",
- "delete-to-relation-text": "Be careful, after the confirmation the entity '{{entityName}}' will be unrelated from the current entity.",
- "delete-to-relations-title": "Are you sure you want to delete { count, plural, 1 {1 relation} other {# relations} }?",
- "delete-to-relations-text": "Be careful, after the confirmation all selected relations will be removed and corresponding entities will be unrelated from the current entity.",
- "delete-from-relation-title": "Are you sure you want to delete relation from the entity '{{entityName}}'?",
- "delete-from-relation-text": "Be careful, after the confirmation current entity will be unrelated from the entity '{{entityName}}'.",
- "delete-from-relations-title": "Are you sure you want to delete { count, plural, 1 {1 relation} other {# relations} }?",
- "delete-from-relations-text": "Be careful, after the confirmation all selected relations will be removed and current entity will be unrelated from the corresponding entities.",
- "remove-relation-filter": "Remove relation filter",
- "add-relation-filter": "Add relation filter",
- "any-relation": "Any relation",
- "relation-filters": "Relation filters",
- "additional-info": "Additional info (JSON)",
- "invalid-additional-info": "Unable to parse additional info json."
+ "from-relations": "Relaciones salientes",
+ "to-relations": "Relaciones entrantes",
+ "selected-relations": "{ count, plural, 1 {1 relation} other {# relations} } selecciondas",
+ "type": "Tipo",
+ "to-entity-type": "Hacia tipo de entidad",
+ "to-entity-name": "Hacia nombre de entidad",
+ "from-entity-type": "Desde tipo de entidad",
+ "from-entity-name": "Desde nombre de entidad",
+ "to-entity": "Hacia entidad",
+ "from-entity": "Desde entidad",
+ "delete": "Eliminar relación",
+ "relation-type": "Tipo de relación",
+ "relation-type-required": "Tipo de relación es requerido.",
+ "any-relation-type": "Algún tipo",
+ "add": "Agregar relación",
+ "edit": "Editar relación",
+ "delete-to-relation-title": "¿Está seguro de que desea eliminar la relación hacia la entidad '{{entityName}}'?",
+ "delete-to-relation-text": "Tener cuidado, después de la confirmación, la entidad '{{entityName}}' no estará relacionada desde la entidad actual.",
+ "delete-to-relations-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 relation} other {# relations} }?",
+ "delete-to-relations-text": "Tener cuidado, después de la confirmación, se eliminarán todas las relaciones seleccionadas y las entidades correspondientes no estarán relacionadas desde la entidad actual.",
+ "delete-from-relation-title": "¿Está seguro de que desea eliminar la relación desde la entidad '{{entityName}}'?",
+ "delete-from-relation-text": "Tener cuidado, después de la confirmación, la entidad actual no será relacionada desde la entidad '{{entityName}}'.",
+ "delete-from-relations-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 relation} other {# relations} }?",
+ "delete-from-relations-text": "Tener cuidado, después de la confirmación, se eliminarán todas las relaciones seleccionadas y la entidad actual no será relacionada desde las correspondientes entidades.",
+ "remove-relation-filter": "Eliminar filtro de relación",
+ "add-relation-filter": "Agregar filtro de relación",
+ "any-relation": "Alguna relación",
+ "relation-filters": "Filtros de relación",
+ "additional-info": "Información adicional (JSON)",
+ "invalid-additional-info": "No se puede analizar información adicional json."
},
"rulechain": {
- "rulechain": "Rule chain",
- "rulechains": "Rule chains",
- "root": "Root",
- "delete": "Delete rule chain",
- "name": "Name",
- "name-required": "Name is required.",
- "description": "Description",
- "add": "Add Rule Chain",
- "set-root": "Make rule chain root",
- "set-root-rulechain-title": "Are you sure you want to make the rule chain '{{ruleChainName}}' root?",
- "set-root-rulechain-text": "After the confirmation the rule chain will become root and will handle all incoming transport messages.",
- "delete-rulechain-title": "Are you sure you want to delete the rule chain '{{ruleChainName}}'?",
- "delete-rulechain-text": "Be careful, after the confirmation the rule chain and all related data will become unrecoverable.",
- "delete-rulechains-title": "Are you sure you want to delete { count, plural, 1 {1 rule chain} other {# rule chains} }?",
- "delete-rulechains-action-title": "Delete { count, plural, 1 {1 rule chain} other {# rule chains} }",
- "delete-rulechains-text": "Be careful, after the confirmation all selected rule chains will be removed and all related data will become unrecoverable.",
- "add-rulechain-text": "Add new rule chain",
- "no-rulechains-text": "No rule chains found",
- "rulechain-details": "Rule chain details",
- "details": "Details",
- "events": "Events",
- "system": "System",
- "import": "Import rule chain",
- "export": "Export rule chain",
- "export-failed-error": "Unable to export rule chain: {{error}}",
- "create-new-rulechain": "Create new rule chain",
- "rulechain-file": "Rule chain file",
- "invalid-rulechain-file-error": "Unable to import rule chain: Invalid rule chain data structure.",
- "copyId": "Copy rule chain Id",
- "idCopiedMessage": "Rule chain Id has been copied to clipboard",
- "select-rulechain": "Select rule chain",
- "no-rulechains-matching": "No rule chains matching '{{entity}}' were found.",
- "rulechain-required": "Rule chain is required",
- "management": "Rules management",
- "debug-mode": "Debug mode"
+ "rulechain": "Cadena de reglas",
+ "rulechains": "Cadenas de reglas",
+ "root": "Raíz",
+ "delete": "Eliminar cadena de reglas",
+ "name": "Nombre",
+ "name-required": "El nombre es requerido.",
+ "description": "Descripción",
+ "add": "Agregar cadena de reglas",
+ "set-root": "Hacer la cadena de reglas raíz",
+ "set-root-rulechain-title": "¿Está seguro de que desea hacer la cadena de reglas '{{ruleChainName}}' root?",
+ "set-root-rulechain-text": "Después de la confirmación, la cadena de reglas se volverá raíz y manejará todos los mensajes de transporte entrantes.",
+ "delete-rulechain-title": "¿Está seguro de que desea eliminar la cadena de reglas '{{ruleChainName}}'?",
+ "delete-rulechain-text": "Tener cuidado, después de la confirmación, la cadena de reglas y todos los datos relacionados se volverán irrecuperables.",
+ "delete-rulechains-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 rule chain} other {# rule chains} }?",
+ "delete-rulechains-action-title": "Eliminar { count, plural, 1 {1 rule chain} other {# rule chains} }",
+ "delete-rulechains-text": "Tener cuidado, después de la confirmación se eliminarán todas las cadenas de reglas seleccionadas y todos los datos relacionados se volverán irrecuperables.",
+ "add-rulechain-text": "Agregar nueva cadena de reglas",
+ "no-rulechains-text": "Cadenas de reglas no encontradas",
+ "rulechain-details": "Detalles de la cadena de reglas",
+ "details": "Detalles",
+ "events": "Eventos",
+ "system": "Sistema",
+ "import": "Importar cadena de reglas",
+ "export": "Exportar cadena de reglas",
+ "export-failed-error": "No se puede exportar la cadena de reglas: {{error}}",
+ "create-new-rulechain": "Crear nueva cadena de reglas",
+ "rulechain-file": "Archivo de la cadena de reglas",
+ "invalid-rulechain-file-error": "No se puede importar la cadena de reglas: Estructura de datos de la cadena de reglas inválida.",
+ "copyId": "Copiar ID de la cadena de reglas",
+ "idCopiedMessage": "ID de la cadena de reglas ha sido copiada al portapapeles",
+ "select-rulechain": "Seleccionar cadena de reglas",
+ "no-rulechains-matching": "Cadenas de reglas que coincidan con '{{entity}}' no fueron encontradas.",
+ "rulechain-required": "Cadena de reglas es requerida",
+ "management": "Gestión de reglas",
+ "debug-mode": "Mode de depuración"
},
"rulenode": {
- "details": "Details",
- "events": "Events",
- "search": "Search nodes",
- "open-node-library": "Open node library",
- "add": "Add rule node",
- "name": "Name",
- "name-required": "Name is required.",
- "type": "Type",
- "description": "Description",
- "delete": "Delete rule node",
- "select-all-objects": "Select all nodes and connections",
- "deselect-all-objects": "Deselect all nodes and connections",
- "delete-selected-objects": "Delete selected nodes and connections",
- "delete-selected": "Delete selected",
- "select-all": "Select all",
- "copy-selected": "Copy selected",
- "deselect-all": "Deselect all",
- "rulenode-details": "Rule node details",
- "debug-mode": "Debug mode",
- "configuration": "Configuration",
- "link": "Link",
- "link-details": "Rule node link details",
- "add-link": "Add link",
- "link-label": "Link label",
- "link-label-required": "Link label is required.",
- "custom-link-label": "Custom link label",
- "custom-link-label-required": "Custom link label is required.",
- "type-filter": "Filter",
- "type-filter-details": "Filter incoming messages with configured conditions",
- "type-enrichment": "Enrichment",
- "type-enrichment-details": "Add additional information into Message Metadata",
- "type-transformation": "Transformation",
- "type-transformation-details": "Change Message payload and Metadata",
- "type-action": "Action",
- "type-action-details": "Perform special action",
- "type-external": "External",
- "type-external-details": "Interacts with external system",
- "type-rule-chain": "Rule Chain",
- "type-rule-chain-details": "Forwards incoming messages to specified Rule Chain",
- "type-input": "Input",
- "type-input-details": "Logical input of Rule Chain, forwards incoming messages to next related Rule Node",
- "directive-is-not-loaded": "Defined configuration directive '{{directiveName}}' is not available.",
- "ui-resources-load-error": "Failed to load configuration ui resources.",
- "invalid-target-rulechain": "Unable to resolve target rule chain!",
- "test-script-function": "Test script function",
- "message": "Message",
- "message-type": "Message type",
- "message-type-required": "Message type is required",
- "metadata": "Metadata",
- "metadata-required": "Metadata entries can't be empty.",
- "output": "Output",
- "test": "Test",
- "help": "Help"
+ "details": "Detalles",
+ "events": "Eventos",
+ "search": "Nodos de búsqueda",
+ "open-node-library": "Abrir libreria de nodos",
+ "add": "Agregar nodo de reglas",
+ "name": "Nombre",
+ "name-required": "El nombre es requerido.",
+ "type": "Tipo",
+ "description": "Descripción",
+ "delete": "Eliminar nodo de reglas",
+ "select-all-objects": "Seleccionar todos los nodos y conexiones",
+ "deselect-all-objects": "Deshacer selección de todos los nodos y conexiones",
+ "delete-selected-objects": "Eliminar nodos y conexiones seleccionados",
+ "delete-selected": "Eliminar seleccionado",
+ "select-all": "Seleccionar todos",
+ "copy-selected": "Copiar seleccionado",
+ "deselect-all": "Deshace selección de todos",
+ "rulenode-details": "Detalles del nodo de reglas",
+ "debug-mode": "Modo de depuración",
+ "configuration": "Configuración",
+ "link": "Enlace",
+ "link-details": "Detalles del enlace del nodo de reglas",
+ "add-link": "Agregar enlace",
+ "link-label": "Etiqueta del enlace",
+ "link-label-required": "Etiqueta del enlace es requerida.",
+ "custom-link-label": "Etiqueta del enlace personalizada",
+ "custom-link-label-required": "Etiqueta del enlace personalizado es requerida.",
+ "link-labels": "Etiquetas del enlace",
+ "link-labels-required": "Etiquetas del enlace son requeridas.",
+ "no-link-labels-found": "Etiquetas de enlaces no encontradas",
+ "no-link-label-matching": "'{{label}}' no encontrada.",
+ "create-new-link-label": "Crear una nueva!",
+ "type-filter": "Filtro",
+ "type-filter-details": "Filtrar mensajes entrantes con las condiciones configuradas",
+ "type-enrichment": "Enriquecimiento",
+ "type-enrichment-details": "Agregar información adicional en mensajes de metadatos",
+ "type-transformation": "Transformación",
+ "type-transformation-details": "Cambiar carga útil del Mensaje y Metadatos",
+ "type-action": "Acción",
+ "type-action-details": "Ejecutar acción especial",
+ "type-external": "Externo",
+ "type-external-details": "Interactuar con sistemas externos",
+ "type-rule-chain": "Cadena de reglas",
+ "type-rule-chain-details": "Reenvíar los mensajes entrantes a la cadena de reglas especificada",
+ "type-input": "Entrada",
+ "type-input-details": "Entrada lógica de la Cadena de Reglas, reenvíar los mensajes entrantes al siguiente nodo de regla relacionado.",
+ "type-unknown": "Desconocido",
+ "type-unknown-details": "Regla de nodo no resuelta",
+ "directive-is-not-loaded": "La directiva de configuración definida '{{directiveName}}' no está disponible.",
+ "ui-resources-load-error": "Error al cargar los recursos de configuración ui.",
+ "invalid-target-rulechain": "No se puede resolver la cadena de reglas objetivo!",
+ "test-script-function": "Probar función script",
+ "message": "Mensaje",
+ "message-type": "Tipo de mensaje",
+ "select-message-type": "Seleccionar tipo de mensaje",
+ "message-type-required": "Tipo de mensaje es requerido",
+ "metadata": "Metadatos",
+ "metadata-required": "La entradas de matadatos no pueden estar vacías.",
+ "output": "Salida",
+ "test": "Prueba",
+ "help": "Ayuda"
},
"tenant": {
- "tenants": "Tenants",
- "management": "Gestión de Tenant",
- "add": "Agregar Tenant",
- "admins": "Admins",
- "manage-tenant-admins": "Gestionar administradores tenant",
- "delete": "Eliminar tenant",
- "add-tenant-text": "Agregar nuevo tenant",
- "no-tenants-text": "Ningún tenant encontrado",
- "tenant-details": "Detalles del Tenant",
- "delete-tenant-title": "¿Estás seguro que quieres eliminar el tenant '{{tenantTitle}}'?",
- "delete-tenant-text": "Ten cuidado, luego de confirmar el tenant será eliminado y la información relacionada será irrecuperable.",
- "delete-tenants-title": "¿Estás seguro que quieres eliminar { count, plural, 1 {1 tenant} other {# tenants} }?",
+ "tenant": "Organización",
+ "tenants": "Organizaciones",
+ "management": "Gestión de la organización",
+ "add": "Agregar Organización",
+ "admins": "Administradores",
+ "manage-tenant-admins": "Gestionar administradores de la organización",
+ "delete": "Eliminar organización",
+ "add-tenant-text": "Agregar nueva organización",
+ "no-tenants-text": "Organizaciones no encontradas",
+ "tenant-details": "Detalles de la organización",
+ "delete-tenant-title": "¿Está seguro de que desea eliminar la organización '{{tenantTitle}}'?",
+ "delete-tenant-text": "Tener cuidado, después de la confirmación, la organización y todos los datos relacionados se volverán irrecuperables.",
+ "delete-tenants-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 tenant} other {# tenants} }?",
"delete-tenants-action-title": "Eliminar { count, plural, 1 {1 tenant} other {# tenants} }",
- "delete-tenants-text": "Ten cuidado, luego de confirmar los tenants seleccionados serán eliminados y la información relacionada será irrecuperable.",
+ "delete-tenants-text": "Tener cuidado, después de la confirmación se eliminarán todas las organizaciones seleccionadas y todos los datos relacionados se volverán irrecuperables.",
"title": "Título",
- "title-required": "Título requerido.",
- "description": "Descripción"
+ "title-required": "Título es requerido.",
+ "description": "Descripción",
+ "details": "Detalles",
+ "events": "Eventos",
+ "copyId": "Copiar ID de la organización",
+ "idCopiedMessage": "ID de la organización ha sido copiado al portapapeles",
+ "select-tenant": "Seleccionar organización",
+ "no-tenants-matching": "Organizaciones que coincidan con '{{entity}}' no fueron encontradas.",
+ "tenant-required": "Organización es requerida"
},
"timeinterval": {
- "seconds-interval": "{ seconds, plural, 1 {1 segundo} other {# segundos} }",
- "minutes-interval": "{ minutes, plural, 1 {1 minuto} other {# minutos} }",
- "hours-interval": "{ hours, plural, 1 {1 hora} other {# horas} }",
- "days-interval": "{ days, plural, 1 {1 día} other {# días} }",
+ "seconds-interval": "{ seconds, plural, 1 {1 second} other {# seconds} }",
+ "minutes-interval": "{ minutes, plural, 1 {1 minute} other {# minutes} }",
+ "hours-interval": "{ hours, plural, 1 {1 hour} other {# hours} }",
+ "days-interval": "{ days, plural, 1 {1 day} other {# days} }",
"days": "Días",
"hours": "Horas",
"minutes": "Minutos",
@@ -1110,209 +1309,248 @@
"advanced": "Avanzado"
},
"timewindow": {
- "days": "{ days, plural, 1 { día } other {# días } }",
- "hours": "{ hours, plural, 0 { horas } 1 {1 hora } other {# horas } }",
- "minutes": "{ minutes, plural, 0 { minutos } 1 {1 minuto } other {# minutos } }",
- "seconds": "{ seconds, plural, 0 { segundos } 1 {1 segundo } other {# segundos } }",
- "realtime": "Tiempo-real",
- "history": "Histórico",
- "last-prefix": "último",
- "period": "desde {{ startTime }} hasta {{ endTime }}",
- "edit": "Editar ventana de tiempo",
- "date-range": "Rango de fechas",
- "last": "Últimos",
+ "days": "{ days, plural, 1 { day } other {# days } }",
+ "hours": "{ hours, plural, 0 { hour } 1 {1 hour } other {# hours } }",
+ "minutes": "{ minutes, plural, 0 { minute } 1 {1 minute } other {# minutes } }",
+ "seconds": "{ seconds, plural, 0 { second } 1 {1 second } other {# seconds } }",
+ "realtime": "Tiempo real",
+ "history": "Historia",
+ "last-prefix": "última",
+ "period": "desde {{ startTime }} to {{ endTime }}",
+ "edit": "Editat ventana de tiempo",
+ "date-range": "Rango de fecha",
+ "last": "Última",
"time-period": "Período de tiempo"
},
"user": {
+ "user": "Usuario",
"users": "Usuarios",
- "customer-users": "Usuarios del Cliente",
- "tenant-admins": "Tenant Admins",
- "sys-admin": "Administrador del Sistema",
- "tenant-admin": "Administrador Tenant",
+ "customer-users": "Usuarios cliente",
+ "tenant-admins": "Administradores de la Organización",
+ "sys-admin": "Administrador del sistema",
+ "tenant-admin": "Administrador de la organización",
"customer": "Cliente",
"anonymous": "Anónimo",
- "add": "Agregar usuario",
+ "add": "Agregar Usuario",
"delete": "Eliminar usuario",
"add-user-text": "Agregar nuevo usuario",
- "no-users-text": "Ningún usuario encontrado",
- "user-details": "Detalles del usuario",
- "delete-user-title": "¿Estás seguro que quieres eliminar el usuario '{{userEmail}}'?",
- "delete-user-text": "Ten cuidado, luego de confirmar el usuario seleccionado será eliminado y la información relacionada será irrecuperable.",
- "delete-users-title": "¿Estás seguro que quieres eliminar { count, plural, 1 {1 usuario} other {# usuarios} }?",
- "delete-users-action-title": "Borrar { count, plural, 1 {1 usuario} other {# usuarios} }",
- "delete-users-text": "Ten cuidado, luego de confirmar los usuarios seleccionados serán eliminados y la información relacionada será irrecuperable.",
- "activation-email-sent-message": "Mail de activación enviado con éxito!",
+ "no-users-text": "Usuarios no encontrados",
+ "user-details": "Detalles de usuario",
+ "delete-user-title": "¿Está seguro de que desea eliminar el usuario '{{userEmail}}'?",
+ "delete-user-text": "Tener cuidado, después de la confirmación, el usuario y todos los datos relacionados se volverán irrecuperables.",
+ "delete-users-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 user} other {# users} }?",
+ "delete-users-action-title": "Delete { count, plural, 1 {1 user} other {# users} }",
+ "delete-users-text": "Tener cuidado, después de la confirmación se eliminarán todas los usuarios seleccionados y todos los datos relacionados se volverán irrecuperables.",
+ "activation-email-sent-message": "Correo electrónico de activación fue enviado exitosamente!",
"resend-activation": "Reenviar activación",
- "email": "Email",
- "email-required": "Email requerido.",
+ "email": "Correo electrónico",
+ "email-required": "Correo electrónico es requerido.",
+ "invalid-email-format": "Formato de correo electrónico inválido.",
"first-name": "Nombre",
"last-name": "Apellido",
"description": "Descripción",
- "default-dashboard": "Panel por defecto",
- "always-fullscreen": "Siempre en pantalla completa"
+ "default-dashboard": "Panel predeterminado",
+ "always-fullscreen": "Siempre pantalla completa",
+ "select-user": "Seleccionar usuario",
+ "no-users-matching": "Usuarios que coincidan con '{{entity}}' no fueron encontrados.",
+ "user-required": "Usuario es requerido",
+ "activation-method": "Método de activación",
+ "display-activation-link": "Mostrar enlace de activación",
+ "send-activation-mail": "Enviar correo electrónico de activación",
+ "activation-link": "Enlace de activación de usuario",
+ "activation-link-text": "Para activar el usuario, utilizar los siguientes <a href='{{activationLink}}' target='_blank'>activation link</a> :",
+ "copy-activation-link": "Copiar enlace de activación",
+ "activation-link-copied-message": "El enlace de activación de usuario ha sido copiado al portapapeles",
+ "details": "Detalles",
+ "login-as-tenant-admin": "Iniciar sesión como Administrador de la Organización",
+ "login-as-customer-user": "Iniciar sesión como Usuario Cliente"
},
"value": {
"type": "Tipo de valor",
- "string": "Cadena de texto",
- "string-value": "Valor de cadena de texto",
- "integer": "Nro entero",
- "integer-value": "Valor de nro entero",
- "invalid-integer-value": "Valor inválido",
- "double": "Nro decimal",
- "double-value": "Valor nro decimal",
+ "string": "Cadena de caracteres",
+ "string-value": "Valor de la cadena de caracteres",
+ "integer": "Entero",
+ "integer-value": "Valor entero",
+ "invalid-integer-value": "Valor de entero inválido",
+ "double": "Doble",
+ "double-value": "Valor doble",
"boolean": "Booleano",
"boolean-value": "Valor booleano",
"false": "Falso",
- "true": "Verdadero"
+ "true": "Verdadero",
+ "long": "Largo"
},
"widget": {
- "widget-library": "Bibloteca de Widgets",
- "widget-bundle": "Paquetes de Widgets",
+ "widget-library": "Libreria de Widgets",
+ "widget-bundle": "Paquete de Widgets",
"select-widgets-bundle": "Seleccionar paquete de widgets",
- "management": "Gestión de Widgets",
- "editor": "Editor de widgets",
- "widget-type-not-found": "Problema al cargar la configuración del widget.<br>Probablemente asociado\n El tipo de widget fue eliminado.",
- "widget-type-load-error": "Widget no pudo ser cargado debido a estos errores:",
+ "management": "Gestión de widget",
+ "editor": "Editor de Widget",
+ "widget-type-not-found": "Problema cargando configuración de widget.<br>Probablemente tipo de widget asociado fue eliminado.",
+ "widget-type-load-error": "El widget no fue cargado debido a los siguientes errores:",
"remove": "Eliminar widget",
"edit": "Editar widget",
- "remove-widget-title": "¿Estás seguro que quieres eliminar el widget '{{widgetTitle}}'?",
- "remove-widget-text": "Luego de confirmar el widget será eliminado y toda la información relacionada será irrecuperable..",
- "timeseries": "Series de tiempo",
+ "remove-widget-title": "¿Está seguro de que desea eliminar el widget '{{widgetTitle}}'?",
+ "remove-widget-text": "Después de la confirmación, el widget y todos los datos relacionados se volverán irrecuperables.",
+ "timeseries": "Series temporales",
+ "search-data": "Buscar datos",
+ "no-data-found": "Datos no encontrados",
"latest-values": "Últimos valores",
"rpc": "Widget de control",
+ "alarm": "Widget de alarma",
"static": "Widget estático",
"select-widget-type": "Seleccionar tipo de widget",
- "missing-widget-title-error": "El titulo del widget debe ser especificado!",
+ "missing-widget-title-error": "Título del widget debe ser especificado!",
"widget-saved": "Widget guardado",
- "unable-to-save-widget-error": "Imposible guardar widget! Tiene errores!",
+ "unable-to-save-widget-error": "No se puede guardar widget! El widget tiene errores!",
"save": "Guardar widget",
"saveAs": "Guardar widget como",
"save-widget-type-as": "Guardar tipo de widget como",
- "save-widget-type-as-text": "Por favor, ingrese un nuevo titulo y/o seleccione un paquete de destino.",
- "toggle-fullscreen": "Cambiar a pantalla completa",
- "run": "Correr widget",
- "title": "Titulo",
- "title-required": "Titulo requerido.",
- "type": "Tipo",
+ "save-widget-type-as-text": "Por favor ingresar nuevo título del widget y/o seleccionar paquete de widgets objetivo",
+ "toggle-fullscreen": "Alternar pantalla completa",
+ "run": "Ejecutar widget",
+ "title": "Título del widget",
+ "title-required": "Título del widget es requerido.",
+ "type": "Tipo de widget",
"resources": "Recursos",
"resource-url": "JavaScript/CSS URL",
"remove-resource": "Eliminar recurso",
- "add-resource": "Agregar recurso",
+ "add-resource": "Agregar recursose",
"html": "HTML",
- "tidy": "Tidy",
+ "tidy": "Ordenado",
"css": "CSS",
"settings-schema": "Esquema de configuración",
"datakey-settings-schema": "Esquema de configuración de clave de datos",
"javascript": "Javascript",
- "remove-widget-type-title": "¿Estás seguro que quieres eliminar el tipo del widget '{{widgetName}}'?",
- "remove-widget-type-text": "Luego de confirmar el tipo será eliminado y la información relacionada será irrecuperable.",
- "remove-widget-type": "Eliminar tipo de widget.",
+ "remove-widget-type-title": "¿Está seguro de que desea eliminar el tipo de widget '{{widgetName}}'?",
+ "remove-widget-type-text": "Después de la confirmación, el tipo de widget y todos los datos relacionados se volverán irrecuperables.",
+ "remove-widget-type": "Eliminar tipo de widget",
"add-widget-type": "Agregar nuevo tipo de widget",
- "widget-type-load-failed-error": "Error al cargar el tipo de widget!",
- "widget-template-load-failed-error": "Error al cargar el template del widget!",
+ "widget-type-load-failed-error": "Failed to load widget type!",
+ "widget-template-load-failed-error": "Error al cargar la plantilla del widget!",
"add": "Agregar Widget",
- "undo": "Deshacer cambios",
+ "undo": "Deshacer cambios en el widget",
"export": "Exportar widget"
},
"widget-action": {
- "header-button": "Widget header button",
- "open-dashboard-state": "Navigate to new dashboard state",
- "update-dashboard-state": "Update current dashboard state",
- "open-dashboard": "Navigate to other dashboard",
- "custom": "Custom action",
- "target-dashboard-state": "Target dashboard state",
- "target-dashboard-state-required": "Target dashboard state is required",
- "set-entity-from-widget": "Set entity from widget",
- "target-dashboard": "Target dashboard",
- "open-right-layout": "Open right dashboard layout (mobile view)"
+ "header-button": "Botón del encabezado del widget",
+ "open-dashboard-state": "Navegar a nuevo estado del panel",
+ "update-dashboard-state": "Actualizar estado vigente del panel",
+ "open-dashboard": "Navegar a otro panel",
+ "custom": "Acción personalizada",
+ "target-dashboard-state": "Estado del panel objetivo",
+ "target-dashboard-state-required": "Estado del panel objetivo es requerido",
+ "set-entity-from-widget": "Asignar entidad desde widget",
+ "target-dashboard": "Panel objetivo",
+ "open-right-layout": "Abrir diseño del panel derecho (vista móvil)"
},
"widgets-bundle": {
"current": "Paquete actual",
- "widgets-bundles": "Paquete de Widgets",
- "add": "Agregar paquete de widgets",
- "delete": "Eliminar paquete de widgets",
+ "widgets-bundles": "Paquetes de Widgets",
+ "add": "Agregar Paquete de Widgets",
+ "delete": "Eliminar paquete de widget",
"title": "Título",
- "title-required": "Título requerido.",
+ "title-required": "Título es requerido.",
"add-widgets-bundle-text": "Agregar nuevo paquete de widgets",
- "no-widgets-bundles-text": "Ningún paquete de widgets encontrado",
- "empty": "Paquete de widgets vacío.",
+ "no-widgets-bundles-text": "Paquetes de widgets no encontrados",
+ "empty": "Paquete de widgets está vacío",
"details": "Detalles",
- "widgets-bundle-details": "Detalles del paquete de Widgets",
- "delete-widgets-bundle-title": "¿Estás seguro que desea eliminar el paquete de widgets '{{widgetsBundleTitle}}'?",
- "delete-widgets-bundle-text": "Ten cuidado, luego de confirmar todos los paquetes seleccionados serán eliminados y su información relacionada será irrecuperable.",
- "delete-widgets-bundles-title": "¿Estás seguro que deseas eliminar { count, plural, 1 {1 paquete de widgets} other {# paquetes de widgets} }?",
- "delete-widgets-bundles-action-title": "Eliminar { count, plural, 1 {1 paquete de widgets} other {# paquetes de widgets} }",
- "delete-widgets-bundles-text": "Ten cuidado, luego de confirmar todos los paquetes seleccionados serán eliminados y la información relacionada será irrecuperable.",
- "no-widgets-bundles-matching": "Ningún paquete '{{widgetsBundle}}' encontrado.",
- "widgets-bundle-required": "Paquete de widget requerido.",
+ "widgets-bundle-details": "Detalles del paquete de widgets",
+ "delete-widgets-bundle-title": "¿Está seguro de que desea eliminar el paquete de widgets '{{widgetsBundleTitle}}'?",
+ "delete-widgets-bundle-text": "Tener cuidado, después de la confirmación, el paquete de widgets y todos los datos relacionados se volverán irrecuperables.",
+ "delete-widgets-bundles-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 widgets bundle} other {# widgets bundles} }?",
+ "delete-widgets-bundles-action-title": "Eliminar { count, plural, 1 {1 widgets bundle} other {# widgets bundles} }",
+ "delete-widgets-bundles-text": "Tener cuidado, después de la confirmación se eliminarán todas los paquetes de widgets seleccionados y todos los datos relacionados se volverán irrecuperables.",
+ "no-widgets-bundles-matching": "Paquetes de widgets que coincidan con '{{widgetsBundle}}' no fueron encontrados.",
+ "widgets-bundle-required": "Paquete de widgets es requerido.",
"system": "Sistema",
"import": "Importar paquete de widgets",
"export": "Exportar paquete de widgets",
- "export-failed-error": "Imposible exportar paquete de widgets: {{error}}",
+ "export-failed-error": "No se puede exportar paquete de widgets: {{error}}",
"create-new-widgets-bundle": "Crear nuevo paquete de widgets",
"widgets-bundle-file": "Archivo de paquete de widgets",
- "invalid-widgets-bundle-file-error": "Imposible importar paquete de widgets: Estructura de datos inválida."
+ "invalid-widgets-bundle-file-error": "No se puede importar paquete de widgets: Estructura de datos del paquete de widgets inválida."
},
"widget-config": {
"data": "Datos",
- "settings": "Ajustes",
+ "settings": "Configuración",
"advanced": "Avanzado",
- "title": "Titulo",
- "general-settings": "Ajustes generales",
- "display-title": "Mostrar titulo",
- "drop-shadow": "Sombra",
+ "title": "Título",
+ "general-settings": "Configuaración general",
+ "display-title": "Mostrar título",
+ "drop-shadow": "Colocar sombra",
"enable-fullscreen": "Habilitar pantalla completa",
"background-color": "Color de fondo",
"text-color": "Color del texto",
"padding": "Relleno",
- "title-style": "Estilo de título",
- "mobile-mode-settings": "Ajustes mobile.",
+ "margin": "Margen",
+ "widget-style": "Estilo del widget",
+ "title-style": "Estilo del título",
+ "mobile-mode-settings": "Configuración del modo móvil",
"order": "Orden",
"height": "Altura",
- "units": "Caracter especial a mostrar en el siguiente valor",
- "decimals": "Números de dígitos después de la coma",
+ "units": "Símbolo especial para mostrar junto al valor.",
+ "decimals": "Número de dígitos después del punto flotante",
"timewindow": "Ventana de tiempo",
- "use-dashboard-timewindow": "Usar ventana de tiempo del Panel",
+ "use-dashboard-timewindow": "Utilizar ventana de timpo del panel",
"display-legend": "Mostrar leyenda",
- "datasources": "Set de datos",
+ "datasources": "Fuentes de datos",
+ "maximum-datasources": "Máximo { count, plural, 1 {1 datasource is allowed.} other {# datasources are allowed} }",
"datasource-type": "Tipo",
- "datasource-parameters": "Parámetros",
- "remove-datasource": "Eliminar set de datos",
- "add-datasource": "Agregar set de datos",
- "target-device": "Dispositivo destino"
+ "datasource-parameters": "Parametros",
+ "remove-datasource": "Eliminar fuente de datos",
+ "add-datasource": "Agregar fuente de datos",
+ "target-device": "Dispositivo objetivo",
+ "alarm-source": "Fuente de alarma",
+ "actions": "Accines",
+ "action": "Acción",
+ "add-action": "Agregar acción",
+ "search-actions": "Buscar acciones",
+ "action-source": "Fuente de acción",
+ "action-source-required": "Fuente de acción es requerida.",
+ "action-name": "Nombre",
+ "action-name-required": "Nombre de acción es requerido.",
+ "action-name-not-unique": "Ya existe otra acción con el mismo nombre.<br/>El nombre de la acción debe ser único dentro de la misma fuente de acción.",
+ "action-icon": "Icono",
+ "action-type": "Tipo",
+ "action-type-required": "Tipo de acción es requerido.",
+ "edit-action": "Editar acción",
+ "delete-action": "Eliminar acción",
+ "delete-action-title": "Eliminar acción del widget",
+ "delete-action-text": "¿Está seguro de que desea eliminar la acción del widget con nombre '{{actionName}}'?"
},
"widget-type": {
"import": "Importar tipo de widget",
"export": "Exportar tipo de widget",
- "export-failed-error": "Imposible exportar tipo de widget: {{error}}",
+ "export-failed-error": "No se puede exportar tipo de widget: {{error}}",
"create-new-widget-type": "Crear nuevo tipo de widget",
- "widget-type-file": "Tipo de archivo del widget",
- "invalid-widget-type-file-error": "Imposible de importar tipo de widget: Estructura de datos inválida."
+ "widget-type-file": "Archivo de tipo de widget",
+ "invalid-widget-type-file-error": "No se puede importar tipo de widget: Estructura de datos del tipo de widget es inválida."
},
"icon": {
- "icon": "Icon",
- "select-icon": "Select icon",
- "material-icons": "Material icons",
- "show-all": "Show all icons"
+ "icon": "Icono",
+ "select-icon": "Seleccionar icono",
+ "material-icons": "Iconos de maerial",
+ "show-all": "Mostrar todos los iconos"
},
"custom": {
"widget-action": {
- "action-cell-button": "Action cell button",
- "row-click": "On row click",
- "marker-click": "On marker click",
- "tooltip-tag-action": "Tooltip tag action"
+ "action-cell-button": "Botón de acción de celda",
+ "row-click": "Clic en la fila",
+ "marker-click": "Clic en el marcador",
+ "tooltip-tag-action": "Acción de etiqueta para globo de ayuda"
}
},
"language": {
"language": "Lenguaje",
"locales": {
+ "fr_FR": "Francés",
+ "zh_CN": "Chino",
"en_US": "Inglés",
- "fr_FR": "Francés",
+ "it_IT": "Italiano",
"ko_KR": "Coreano",
- "zh_CN": "Chino",
"ru_RU": "Ruso",
"es_ES": "Español",
- "it_IT": "Italiano",
"ja_JA": "Japonés",
"TR": "Turco"
}
ui/src/app/widget/lib/google-map.js 2(+1 -1)
diff --git a/ui/src/app/widget/lib/google-map.js b/ui/src/app/widget/lib/google-map.js
index 25bf510..2fe7ce4 100644
--- a/ui/src/app/widget/lib/google-map.js
+++ b/ui/src/app/widget/lib/google-map.js
@@ -44,7 +44,7 @@ export default class TbGoogleMap {
function initGoogleMap() {
tbMap.map = new google.maps.Map($containerElement[0], { // eslint-disable-line no-undef
- scrollwheel: false,
+ scrollwheel: true,
mapTypeId: getGoogleMapTypeId(tbMap.defaultMapType),
zoom: tbMap.defaultZoomLevel || 8
});