diff --git a/application/src/main/data/json/tenant/dashboards/gateways.json b/application/src/main/data/json/tenant/dashboards/gateways.json index d98daa3632..42c4f199b5 100644 --- a/application/src/main/data/json/tenant/dashboards/gateways.json +++ b/application/src/main/data/json/tenant/dashboards/gateways.json @@ -181,12 +181,12 @@ "actions": { "actionCellButton": [ { - "name": "Docker commands", + "name": "Launch command", "icon": "terminal", "useShowWidgetActionFunction": null, "showWidgetActionFunction": "return true;", "type": "customPretty", - "customHtml": "
\n \n

Docker commands

\n \n
\n \n
\n \n
\n \n
\n
\n", + "customHtml": "
\n \n

{{ 'gateway.launch-command' | translate }}

\n \n
\n \n
\n \n
\n \n
\n
\n", "customCss": ".container {\n display: grid;\n grid-template-rows: min-content minmax(auto, 1fr) min-content;\n height: 100%;\n max-height: 100vh;\n width: 600px;\n max-width: 100%;\n}", "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\n\nopenCommands();\n\nfunction openCommands() {\n customDialog.customDialog(htmlTemplate, CommandsDialogController, {panelClass: \"test\"}).subscribe();\n}\n\nfunction CommandsDialogController(instance) {\n let vm = instance;\n \n vm.entityId = entityId.id;\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n}\n", "customResources": [], @@ -1861,7 +1861,7 @@ "padding": "8px", "settings": { "useMarkdownTextFunction": false, - "markdownTextPattern": "
\r\n \r\n
", + "markdownTextPattern": "
\r\n \r\n
", "applyDefaultMarkdownStyle": false, "markdownCss": ".action-buttons-container {\r\n display: flex;\r\n flex-wrap: wrap;\r\n flex-direction: row;\r\n height: 100%;\r\n width: 100%;\r\n align-content: center;\r\n}\r\n\r\nbutton {\r\n flex-grow: 1;\r\n margin: 10px;\r\n min-width: 150px;\r\n height: auto;\r\n}" }, @@ -1887,7 +1887,7 @@ "useShowWidgetActionFunction": null, "showWidgetActionFunction": "return true;", "type": "customPretty", - "customHtml": "
\n \n

Launch command

\n \n
\n \n
\n \n
\n \n
\n
\n", + "customHtml": "
\n \n

{{ 'gateway.launch-command' | translate }}

\n \n
\n \n
\n \n
\n \n
\n
\n", "customCss": ".container {\n display: grid;\n grid-template-rows: min-content minmax(auto, 1fr) min-content;\n height: 100%;\n max-height: 100vh;\n width: 600px;\n max-width: 100%;\n}", "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\n\nopenCommands();\n\nfunction openCommands() {\n customDialog.customDialog(htmlTemplate, CommandsDialogController, {panelClass: \"test\"}).subscribe();\n}\n\nfunction CommandsDialogController(instance) {\n let vm = instance;\n \n vm.entityId = entityId.id;\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n}\n", "customResources": [], diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index e78313f6d8..535700335d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -16,6 +16,7 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -350,11 +351,11 @@ public class AlarmController extends BaseController { @PathVariable(ENTITY_TYPE) String strEntityType, @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_ID) String strEntityId, - @Parameter(description = ALARM_QUERY_SEARCH_STATUS_ARRAY_DESCRIPTION, schema = @Schema(allowableValues = {"ANY", "ACTIVE", "CLEARED", "ACK", "UNACK"})) + @Parameter(description = ALARM_QUERY_SEARCH_STATUS_ARRAY_DESCRIPTION, array = @ArraySchema(schema = @Schema(type = "string", allowableValues = {"ANY", "ACTIVE", "CLEARED", "ACK", "UNACK"}))) @RequestParam(required = false) String[] statusList, - @Parameter(description = ALARM_QUERY_SEVERITY_ARRAY_DESCRIPTION, schema = @Schema(allowableValues = {"CRITICAL", "MAJOR", "MINOR", "WARNING", "INDETERMINATE"})) + @Parameter(description = ALARM_QUERY_SEVERITY_ARRAY_DESCRIPTION, array = @ArraySchema(schema = @Schema(type = "string", allowableValues = {"CRITICAL", "MAJOR", "MINOR", "WARNING", "INDETERMINATE"}))) @RequestParam(required = false) String[] severityList, - @Parameter(description = ALARM_QUERY_TYPE_ARRAY_DESCRIPTION) + @Parameter(description = ALARM_QUERY_TYPE_ARRAY_DESCRIPTION, array = @ArraySchema(schema = @Schema(type = "string"))) @RequestParam(required = false) String[] typeList, @Parameter(description = ALARM_QUERY_ASSIGNEE_DESCRIPTION) @RequestParam(required = false) String assigneeId, @@ -412,11 +413,11 @@ public class AlarmController extends BaseController { @RequestMapping(value = "/v2/alarms", method = RequestMethod.GET) @ResponseBody public PageData getAllAlarmsV2( - @Parameter(description = ALARM_QUERY_SEARCH_STATUS_ARRAY_DESCRIPTION, schema = @Schema(allowableValues = {"ANY", "ACTIVE", "CLEARED", "ACK", "UNACK"})) + @Parameter(description = ALARM_QUERY_SEARCH_STATUS_ARRAY_DESCRIPTION, array = @ArraySchema(schema = @Schema(type = "string", allowableValues = {"ANY", "ACTIVE", "CLEARED", "ACK", "UNACK"}))) @RequestParam(required = false) String[] statusList, - @Parameter(description = ALARM_QUERY_SEVERITY_ARRAY_DESCRIPTION, schema = @Schema(allowableValues = {"CRITICAL", "MAJOR", "MINOR", "WARNING", "INDETERMINATE"})) + @Parameter(description = ALARM_QUERY_SEVERITY_ARRAY_DESCRIPTION, array = @ArraySchema(schema = @Schema(type = "string", allowableValues = {"CRITICAL", "MAJOR", "MINOR", "WARNING", "INDETERMINATE"}))) @RequestParam(required = false) String[] severityList, - @Parameter(description = ALARM_QUERY_TYPE_ARRAY_DESCRIPTION) + @Parameter(description = ALARM_QUERY_TYPE_ARRAY_DESCRIPTION, array = @ArraySchema(schema = @Schema(type = "string"))) @RequestParam(required = false) String[] typeList, @Parameter(description = ALARM_QUERY_ASSIGNEE_DESCRIPTION) @RequestParam(required = false) String assigneeId, diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 8c03d34e8e..7b4621db28 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -17,6 +17,7 @@ package org.thingsboard.server.controller; import com.google.common.util.concurrent.ListenableFuture; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -354,7 +355,7 @@ public class AssetController extends BaseController { @RequestMapping(value = "/assets", params = {"assetIds"}, method = RequestMethod.GET) @ResponseBody public List getAssetsByIds( - @Parameter(description = "A list of assets ids, separated by comma ','") + @Parameter(description = "A list of assets ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string"))) @RequestParam("assetIds") String[] strAssetIds) throws ThingsboardException, ExecutionException, InterruptedException { checkArrayParameter("assetIds", strAssetIds); SecurityUser user = getCurrentUser(); diff --git a/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java b/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java index 58b9296379..eeb67d7ae8 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java @@ -16,6 +16,7 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; @@ -83,7 +84,7 @@ public class ComponentDescriptorController extends BaseController { @RequestMapping(value = "/components", params = {"componentTypes"}, method = RequestMethod.GET) @ResponseBody public List getComponentDescriptorsByTypes( - @Parameter(description = "List of types of the Rule Nodes, (ENRICHMENT, FILTER, TRANSFORMATION, ACTION or EXTERNAL)", required = true) + @Parameter(description = "List of types of the Rule Nodes, (ENRICHMENT, FILTER, TRANSFORMATION, ACTION or EXTERNAL)", array = @ArraySchema(schema = @Schema(type = "string")), required = true) @RequestParam("componentTypes") String[] strComponentTypes, @Parameter(description = "Type of the Rule Chain", schema = @Schema(allowableValues = {"CORE", "EDGE"})) @RequestParam(value = "ruleChainType", required = false) String strRuleChainType) throws ThingsboardException { diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index fedbd48503..416991a996 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -20,6 +20,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -488,7 +489,7 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/devices", params = {"deviceIds"}, method = RequestMethod.GET) @ResponseBody public List getDevicesByIds( - @Parameter(description = "A list of devices ids, separated by comma ','") + @Parameter(description = "A list of devices ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string"))) @RequestParam("deviceIds") String[] strDeviceIds) throws ThingsboardException, ExecutionException, InterruptedException { checkArrayParameter("deviceIds", strDeviceIds); SecurityUser user = getCurrentUser(); diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index 3042b8f2a1..030cb902a6 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -17,6 +17,7 @@ package org.thingsboard.server.controller; import com.google.common.util.concurrent.ListenableFuture; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -426,7 +427,7 @@ public class EdgeController extends BaseController { @RequestMapping(value = "/edges", params = {"edgeIds"}, method = RequestMethod.GET) @ResponseBody public List getEdgesByIds( - @Parameter(description = "A list of edges ids, separated by comma ','", required = true) + @Parameter(description = "A list of edges ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) @RequestParam("edgeIds") String[] strEdgeIds) throws ThingsboardException, ExecutionException, InterruptedException { checkArrayParameter("edgeIds", strEdgeIds); SecurityUser user = getCurrentUser(); diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java index 8436e8fe35..7634819e39 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java @@ -16,6 +16,8 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -156,7 +158,7 @@ public class NotificationTargetController extends BaseController { SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @GetMapping(value = "/targets", params = {"ids"}) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") - public List getNotificationTargetsByIds(@Parameter(description = "Comma-separated list of uuids representing targets ids", required = true) + public List getNotificationTargetsByIds(@Parameter(description = "Comma-separated list of uuids representing targets ids", array = @ArraySchema(schema = @Schema(type = "string")), required = true) @RequestParam("ids") UUID[] ids, @AuthenticationPrincipal SecurityUser user) { // PE: generic permission diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java index 6948218531..474a2816b1 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java @@ -16,6 +16,8 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; @@ -147,7 +149,7 @@ public class NotificationTemplateController extends BaseController { @RequestParam(required = false) String sortProperty, @Parameter(description = SORT_ORDER_DESCRIPTION) @RequestParam(required = false) String sortOrder, - @Parameter(description = "Comma-separated list of notification types to filter the templates") + @Parameter(description = "Comma-separated list of notification types to filter the templates", array = @ArraySchema(schema = @Schema(type = "string"))) @RequestParam(required = false) NotificationType[] notificationTypes, @AuthenticationPrincipal SecurityUser user) throws ThingsboardException { // PE: generic permission diff --git a/application/src/main/java/org/thingsboard/server/controller/QueueStatsController.java b/application/src/main/java/org/thingsboard/server/controller/QueueStatsController.java index 912a1ca7b2..eee35ee973 100644 --- a/application/src/main/java/org/thingsboard/server/controller/QueueStatsController.java +++ b/application/src/main/java/org/thingsboard/server/controller/QueueStatsController.java @@ -16,6 +16,7 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; @@ -89,7 +90,7 @@ public class QueueStatsController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @GetMapping(value = "/queueStats", params = {"queueStatsIds"}) public List getQueueStatsByIds( - @Parameter(description = "A list of queue stats ids, separated by comma ','", required = true) + @Parameter(description = "A list of queue stats ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) @RequestParam("queueStatsIds") String[] strQueueStatsIds) throws ThingsboardException { checkArrayParameter("queueStatsIds", strQueueStatsIds); List queueStatsIds = new ArrayList<>(); diff --git a/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java b/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java index e646c34e4f..74bc087abf 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java @@ -16,6 +16,7 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -272,7 +273,7 @@ public class TbResourceController extends BaseController { @RequestParam String sortOrder, @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"id", "name"}, requiredMode = Schema.RequiredMode.REQUIRED)) @RequestParam String sortProperty, - @Parameter(description = "LwM2M Object ids.", required = true) + @Parameter(description = "LwM2M Object ids.", array = @ArraySchema(schema = @Schema(type = "string")), required = true) @RequestParam(required = false) String[] objectIds) throws ThingsboardException { return checkNotNull(tbResourceService.findLwM2mObject(getTenantId(), sortOrder, sortProperty, objectIds)); } diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index 5f1de4e3e3..6833a7ddfb 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -447,7 +447,7 @@ public class TelemetryController extends BaseController { public DeferredResult saveEntityTelemetryWithTTL( @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @Parameter(description = TELEMETRY_SCOPE_DESCRIPTION, required = true, schema = @Schema(allowableValues = "ANY")) @PathVariable("scope")AttributeScope scope, + @Parameter(description = TELEMETRY_SCOPE_DESCRIPTION, required = true, schema = @Schema(allowableValues = "ANY")) @PathVariable("scope")String scope, @Parameter(description = "A long value representing TTL (Time to Live) parameter.", required = true)@PathVariable("ttl")Long ttl, @io.swagger.v3.oas.annotations.parameters.RequestBody(description = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody String requestBody) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); diff --git a/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java b/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java index 9c42683b00..ad1ed7824a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java @@ -16,6 +16,7 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -251,7 +252,8 @@ public class TenantProfileController extends BaseController { @GetMapping(value = "/tenantProfiles", params = {"ids"}) @PreAuthorize("hasAuthority('SYS_ADMIN')") - public List getTenantProfilesByIds(@RequestParam("ids") UUID[] ids) { + public List getTenantProfilesByIds(@Parameter(description = "Comma-separated list of tenant profile ids", array = @ArraySchema(schema = @Schema(type = "string"))) + @RequestParam("ids") UUID[] ids) { return tenantProfileService.findTenantProfilesByIds(TenantId.SYS_TENANT_ID, ids); } diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java index f2e3f9192f..4c48dbd434 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java @@ -16,6 +16,7 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -185,7 +186,7 @@ public class WidgetTypeController extends AutoCommitController { @RequestParam(required = false) Boolean fullSearch, @Parameter(description = DEPRECATED_FILTER_PARAM_DESCRIPTION, schema = @Schema(allowableValues = {"ALL", "ACTUAL", "DEPRECATED"})) @RequestParam(required = false) String deprecatedFilter, - @Parameter(description = WIDGET_TYPE_ARRAY_DESCRIPTION, schema = @Schema(allowableValues = {"timeseries", "latest", "control", "alarm", "static"})) + @Parameter(description = WIDGET_TYPE_ARRAY_DESCRIPTION, array = @ArraySchema(schema = @Schema(type = "string", allowableValues = {"timeseries", "latest", "control", "alarm", "static"}))) @RequestParam(required = false) String[] widgetTypeList) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); List widgetTypes = widgetTypeList != null ? Arrays.asList(widgetTypeList) : Collections.emptyList(); @@ -331,7 +332,7 @@ public class WidgetTypeController extends AutoCommitController { @RequestParam(required = false) Boolean fullSearch, @Parameter(description = DEPRECATED_FILTER_PARAM_DESCRIPTION, schema = @Schema(allowableValues = {"ALL", "ACTUAL", "DEPRECATED"})) @RequestParam(required = false) String deprecatedFilter, - @Parameter(description = WIDGET_TYPE_ARRAY_DESCRIPTION, schema = @Schema(allowableValues = {"timeseries", "latest", "control", "alarm", "static"})) + @Parameter(description = WIDGET_TYPE_ARRAY_DESCRIPTION, array = @ArraySchema(schema = @Schema(allowableValues = {"timeseries", "latest", "control", "alarm", "static"}))) @RequestParam(required = false) String[] widgetTypeList) throws ThingsboardException { WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId)); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/EmailNotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/EmailNotificationChannel.java index c7a3d83d8f..2f01e26424 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/channels/EmailNotificationChannel.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/EmailNotificationChannel.java @@ -33,7 +33,7 @@ public class EmailNotificationChannel implements NotificationChannel entityFields = Arrays.asList(new EntityKey(EntityKeyType.ENTITY_FIELD, "queueName"), + List entityFields = Arrays.asList(new EntityKey(EntityKeyType.ENTITY_FIELD, "name"), new EntityKey(EntityKeyType.ENTITY_FIELD, "queueName"), new EntityKey(EntityKeyType.ENTITY_FIELD, "serviceId")); EntityDataQuery query = new EntityDataQuery(entityTypeFilter, pageLink, entityFields, null, null); @@ -705,8 +705,12 @@ public class EntityQueryControllerTest extends AbstractControllerTest { Assert.assertTrue(data.hasNext()); Assert.assertEquals(10, data.getData().size()); data.getData().forEach(entityData -> { - assertThat(entityData.getLatest().get(EntityKeyType.ENTITY_FIELD).get("queueName")).asString().isNotBlank(); - assertThat(entityData.getLatest().get(EntityKeyType.ENTITY_FIELD).get("serviceId")).asString().isNotBlank(); + String queueName = entityData.getLatest().get(EntityKeyType.ENTITY_FIELD).get("queueName").getValue(); + String serviceId = entityData.getLatest().get(EntityKeyType.ENTITY_FIELD).get("serviceId").getValue(); + assertThat(queueName).isNotBlank(); + assertThat(serviceId).isNotBlank(); + assertThat(entityData.getLatest().get(EntityKeyType.ENTITY_FIELD).get("name").getValue()).isEqualTo(queueName + "_" + serviceId); + }); EntityCountQuery countQuery = new EntityCountQuery(entityTypeFilter); diff --git a/dao/src/main/java/org/thingsboard/server/dao/eventsourcing/ActionCause.java b/dao/src/main/java/org/thingsboard/server/dao/eventsourcing/ActionCause.java new file mode 100644 index 0000000000..6b03173f31 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/eventsourcing/ActionCause.java @@ -0,0 +1,20 @@ +/** + * Copyright © 2016-2024 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. + */ +package org.thingsboard.server.dao.eventsourcing; + +public enum ActionCause { + TENANT_DELETION +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/eventsourcing/DeleteEntityEvent.java b/dao/src/main/java/org/thingsboard/server/dao/eventsourcing/DeleteEntityEvent.java index fbae8541e3..016c0dc5ff 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/eventsourcing/DeleteEntityEvent.java +++ b/dao/src/main/java/org/thingsboard/server/dao/eventsourcing/DeleteEntityEvent.java @@ -17,18 +17,20 @@ package org.thingsboard.server.dao.eventsourcing; import lombok.Builder; import lombok.Data; -import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; @Builder @Data public class DeleteEntityEvent { + private final TenantId tenantId; private final EntityId entityId; private final T entity; private final String body; + private final ActionCause cause; @Builder.Default private final long ts = System.currentTimeMillis(); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/housekeeper/CleanUpService.java b/dao/src/main/java/org/thingsboard/server/dao/housekeeper/CleanUpService.java index d64e6ea536..27205a74c1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/housekeeper/CleanUpService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/housekeeper/CleanUpService.java @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.housekeeper.HousekeeperTask; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.msg.housekeeper.HousekeeperClient; +import org.thingsboard.server.dao.eventsourcing.ActionCause; import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; import org.thingsboard.server.dao.relation.RelationService; @@ -59,7 +60,7 @@ public class CleanUpService { if (!skippedEntities.contains(entityType)) { cleanUpRelatedData(tenantId, entityId); } - if (entityType == EntityType.USER) { + if (entityType == EntityType.USER && event.getCause() != ActionCause.TENANT_DELETION) { submitTask(HousekeeperTask.unassignAlarms((User) event.getEntity())); } } catch (Throwable e) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java index 0a8d78fb86..2d2c7bf21c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java @@ -327,12 +327,22 @@ public class DeviceProfileDataValidator extends AbstractHasOtaPackageValidator 65534)) { - throw new DeviceCredentialsValidationException("LwM2M Server ShortServerId must not be less than 1 and more than 65534!"); - } - if (serverConfig.isBootstrapServerIs() && !(serverConfig.getShortServerId() == null || serverConfig.getShortServerId() ==0)) { - throw new DeviceCredentialsValidationException("Bootstrap Server ShortServerId must be null or '0'!"); + + if (serverConfig.getShortServerId() != null) { + if (serverConfig.isBootstrapServerIs()){ + if(serverConfig.getShortServerId() < 0 || serverConfig.getShortServerId() > 65535){ + throw new DeviceCredentialsValidationException("Bootstrap Server ShortServerId must be in range [0 - 65535]!"); + } + } else { + if (serverConfig.getShortServerId() < 1 || serverConfig.getShortServerId() > 65534) { + throw new DeviceCredentialsValidationException("LwM2M Server ShortServerId must be in range [1 - 65534]!"); + } + } + } else { + String serverName = serverConfig.isBootstrapServerIs() ? "Bootstrap Server" : "LwM2M Server"; + throw new DeviceCredentialsValidationException(serverName + " ShortServerId must not be null!"); } + String server = serverConfig.isBootstrapServerIs() ? "Bootstrap Server" : "LwM2M Server"; if (!shortServerIds.add(serverConfig.getShortServerId())) { throw new DeviceCredentialsValidationException(server + " \"Short server Id\" value = " + serverConfig.getShortServerId() + ". This value must be a unique value for all servers!"); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index c125639def..599ac3d918 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -89,10 +89,12 @@ public class EntityKeyMapping { public static final String OWNER_TYPE_SELECT_QUERY = "case when e.customer_id = '" + NULL_UUID + "' " + "then 'TENANT' " + "else 'CUSTOMER' end"; + public static final String QUEUE_STATS_NAME_QUERY = "concat(e.queue_name, '_', e.service_id)"; public static final Map ownerPropertiesFunctions = Map.of( OWNER_NAME, OWNER_NAME_SELECT_QUERY, OWNER_TYPE, OWNER_TYPE_SELECT_QUERY ); + public static final Map queueStatsPropertiesFunctions = Map.of(NAME, QUEUE_STATS_NAME_QUERY); public static final List typedEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, ADDITIONAL_INFO); public static final List widgetEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME); @@ -166,6 +168,7 @@ public class EntityKeyMapping { propertiesFunctions.put(EntityType.ENTITY_VIEW, ownerPropertiesFunctions); propertiesFunctions.put(EntityType.USER, ownerPropertiesFunctions); propertiesFunctions.put(EntityType.DASHBOARD, ownerPropertiesFunctions); + propertiesFunctions.put(EntityType.QUEUE_STATS, queueStatsPropertiesFunctions); Map userEntityAliases = new HashMap<>(); userEntityAliases.put(TITLE, EMAIL); diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java index b17cef53db..e86abdbb8b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java @@ -39,8 +39,6 @@ import org.thingsboard.server.dao.entity.AbstractCachedEntityService; import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; import org.thingsboard.server.dao.mobile.MobileAppSettingsService; -import org.thingsboard.server.dao.notification.NotificationRequestService; -import org.thingsboard.server.dao.notification.NotificationRuleService; import org.thingsboard.server.dao.notification.NotificationSettingsService; import org.thingsboard.server.dao.service.PaginatedRemover; import org.thingsboard.server.dao.service.Validator; @@ -168,8 +166,10 @@ public class TenantServiceImpl extends AbstractCachedEntityService bootstrapServerCredentials) { + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = new Lwm2mDeviceProfileTransportConfiguration(); + TelemetryMappingConfiguration observeAttrConfiguration = JacksonUtil.fromString(observeAttr, TelemetryMappingConfiguration.class); + OtherConfiguration clientLwM2mSettings = JacksonUtil.fromString(CLIENT_LWM2M_SETTINGS, OtherConfiguration.class); + transportConfiguration.setBootstrapServerUpdateEnable(true); + transportConfiguration.setObserveAttr(observeAttrConfiguration); + transportConfiguration.setClientLwM2mSettings(clientLwM2mSettings); + transportConfiguration.setBootstrap(bootstrapServerCredentials); + return transportConfiguration; + } + + private List getBootstrapServerCredentialsNoSec(Integer shortServerId, Integer shortServerIdBs){ + List bootstrap = new ArrayList<>(); + bootstrap.add(getBootstrapServerCredentialNoSec(false, shortServerId, shortServerIdBs)); + bootstrap.add(getBootstrapServerCredentialNoSec(true, shortServerId, shortServerIdBs)); + return bootstrap; + } + + private AbstractLwM2MBootstrapServerCredential getBootstrapServerCredentialNoSec(boolean isBootstrap, Integer shortServerId, Integer shortServerIdBs) { + AbstractLwM2MBootstrapServerCredential bootstrapServerCredential = new NoSecLwM2MBootstrapServerCredential(); + bootstrapServerCredential.setServerPublicKey(""); + bootstrapServerCredential.setShortServerId(isBootstrap ? shortServerIdBs : shortServerId); + bootstrapServerCredential.setBootstrapServerIs(isBootstrap); + bootstrapServerCredential.setHost(isBootstrap ? hostBs : host); + bootstrapServerCredential.setPort(isBootstrap ? portBs : port); + return bootstrapServerCredential; + } } diff --git a/ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.ts b/ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.ts index 21d90e0c12..ac25981f6e 100644 --- a/ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/alias/entity-alias-dialog.component.ts @@ -145,7 +145,7 @@ export class EntityAliasDialogComponent extends DialogComponent self.findIndex(v => v.relationType === value.relationType && isEqual(v.entityTypes, value.entityTypes)) === index && - (value.relationType || value.entityTypes.length) + (value.relationType || value.entityTypes?.length) ); } if (this.alias.filter.type) { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html index 9671d35931..ce07156e2c 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html @@ -20,6 +20,7 @@
diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html index 961af7f808..d5665191ce 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html @@ -32,7 +32,7 @@
- + -
+
widgets.color.gradient-end
-
-
widgets.color.end-value
+
+
widgets.color.end-value
- +
- - + + + +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.scss index 25e14cb0d5..d5dd0b57e5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.scss @@ -23,7 +23,7 @@ .gradient-preview { width: 100%; - padding: 40px 12px 0; + padding: 40px 15px 0; .gradient-background { position: relative; height: 56px; @@ -120,11 +120,13 @@ display: flex; align-items: center; justify-content: center; - width: 33px; + width: 38px; height: 24px; border-radius: 4px; background-color: rgba(0, 0, 0, 0.06); &-text { + text-overflow: ellipsis; + overflow: hidden; font-size: 14px; font-weight: 500; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts index 8b78190f5a..0042f3be4b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts @@ -31,7 +31,7 @@ import { takeUntil } from 'rxjs/operators'; import { CdkDragDrop } from '@angular/cdk/drag-drop'; import { IAliasController } from '@core/api/widget-api.models'; import { DomSanitizer } from '@angular/platform-browser'; -import { coerceBoolean, coerceNumber } from '@shared/decorators/coercion'; +import { coerceBoolean } from '@shared/decorators/coercion'; import { isDefinedAndNotNull } from '@core/utils'; import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models'; import { Datasource } from '@shared/models/widget.models'; @@ -71,11 +71,9 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro datasource: Datasource; @Input() - @coerceNumber() minValue: number; @Input() - @coerceNumber() maxValue: number; @Input() @@ -111,7 +109,9 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro source: [{type: ValueSourceType.constant}], color: ['rgba(255, 0, 0, 1)'] }) - }) + }), + minValue: {value: 0, disabled: isFinite(this.minValue)}, + maxValue: {value: 100, disabled: isFinite(this.maxValue)} }); this.gradientFormGroup.valueChanges.pipe( @@ -119,7 +119,7 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro ).subscribe(() => this.updateModel()); this.gradientFormGroup.get('advancedMode').valueChanges.pipe( takeUntil(this.destroy$) - ).subscribe(() => Promise.resolve().then(() => this.popover?.updatePosition())); + ).subscribe(() => setTimeout(() => {this.popover?.updatePosition();}, 0)); } ngOnDestroy() { @@ -141,6 +141,8 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro writeValue(value: ColorGradientSettings): void { if (isDefinedAndNotNull(value)) { this.gradientFormGroup.get('advancedMode').patchValue(value.advancedMode, {emitEvent: false}); + this.gradientFormGroup.get('minValue').patchValue(isFinite(value.minValue) ? value.minValue : this.minValue, {emitEvent: false}); + this.gradientFormGroup.get('maxValue').patchValue(isFinite(value.maxValue) ? value.maxValue : this.maxValue, {emitEvent: false}); if (value?.gradient?.length) { this.gradientFormGroup.get('gradient').get('start').patchValue(value.gradient[0], {emitEvent: false}); this.gradientFormGroup.get('gradient').get('end').patchValue(value.gradient[value.gradient.length - 1], {emitEvent: false}); @@ -165,10 +167,10 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro this.advancedGradientListFormArray.value.map((v, i) => this.pointer(shift * (i + 1), i+1, null, true)).join('') + `
`; } else { - const point = (+this.maxValue - +this.minValue) / (this.gradientListFormArray.value.length + 1); + const min = this.gradientFormGroup.get('minValue').value || 0; + const max = this.gradientFormGroup.get('maxValue').value || 100; + const point = (+max - +min) / (this.gradientListFormArray.value.length + 1); const shift = 100 / (this.gradientListFormArray.value.length + 1); - const min = isDefinedAndNotNull(this.minValue) ? this.minValue : 0; - const max = isDefinedAndNotNull(this.maxValue) ? this.maxValue : 100; return `
${min}
` + this.gradientListFormArray.value.map((v, i) => this.pointer(shift * (i + 1), i+1, point)).join('') + `
${max}
`; @@ -180,7 +182,8 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro return `
`; } else { return `
` + - `
${Math.floor(+this.minValue + (value * index))}
`; + `
` + + `${Math.floor(+this.gradientFormGroup.get('minValue').value + (value * index))}
`; } } @@ -233,7 +236,7 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro this.gradientListFormArray.removeAt(index); } this.gradientFormGroup.markAsDirty(); - Promise.resolve().then(() => this.popover?.updatePosition()); + setTimeout(() => {this.popover?.updatePosition();}, 0); } gradientDrop(event: CdkDragDrop, advanced = false) { @@ -252,19 +255,18 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro this.gradientListFormArray.push(this.colorGradientControl('rgba(0,0,0,0.87)')); } this.gradientFormGroup.markAsDirty(); - Promise.resolve().then(() => this.popover?.updatePosition()); + setTimeout(() => {this.popover?.updatePosition();}, 0); } updateModel() { + const gradient = this.gradientFormGroup.getRawValue(); this.propagateChange( { - advancedMode: this.gradientFormGroup.value.advancedMode, - gradient: [this.gradientFormGroup.value.gradient.start, - ...this.gradientFormGroup.value.gradient.gradientList.map(item => item.color), - this.gradientFormGroup.value.gradient.end], - gradientAdvanced: [this.gradientFormGroup.value.gradientAdvanced.start, - ...this.gradientFormGroup.value.gradientAdvanced.gradientList, - this.gradientFormGroup.value.gradientAdvanced.end] + advancedMode: gradient.advancedMode, + gradient: [gradient.gradient.start, ...gradient.gradient.gradientList.map(item => item.color), gradient.gradient.end], + gradientAdvanced: [gradient.gradientAdvanced.start, ...gradient.gradientAdvanced.gradientList, gradient.gradientAdvanced.end], + minValue: gradient.minValue, + maxValue: gradient.maxValue } ); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/battery-level-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/battery-level-widget-settings.component.html index c34b51a36b..572c50c392 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/battery-level-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/battery-level-widget-settings.component.html @@ -51,6 +51,8 @@ { }; + private propagateChange = null; private readonly destroy$ = new Subject(); private expendedBlocks: NotificationDeliveryMethod[]; + private propagateChangePending = false; constructor(private fb: FormBuilder, private translate: TranslateService) { @@ -105,7 +106,7 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co this.templateConfigurationForm.valueChanges.pipe( takeUntil(this.destroy$) ).subscribe((value) => { - this.propagateChange(value); + this.updateModel(value); }); } @@ -129,6 +130,12 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co registerOnChange(fn: any): void { this.propagateChange = fn; + if (this.propagateChangePending) { + this.propagateChangePending = false; + Promise.resolve().then(() => { + this.templateConfigurationForm.updateValueAndValidity(); + }); + } } registerOnTouched(fn: any): void { @@ -164,6 +171,14 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co return this.expendedBlocks.includes(name); } + private updateModel(value: Partial) { + if (this.propagateChange) { + this.propagateChange(value); + } else { + this.propagateChangePending = true; + } + } + private updateExpandedForm() { this.expendedBlocks = []; Object.keys(this.templateConfigurationForm.controls).forEach((name: NotificationDeliveryMethod) => { diff --git a/ui-ngx/src/app/shared/models/limited-api.models.ts b/ui-ngx/src/app/shared/models/limited-api.models.ts index 9046d8881f..946d816cfc 100644 --- a/ui-ngx/src/app/shared/models/limited-api.models.ts +++ b/ui-ngx/src/app/shared/models/limited-api.models.ts @@ -46,7 +46,7 @@ export const LimitedApiTranslationMap = new Map( [LimitedApi.TRANSPORT_MESSAGES_PER_TENANT, 'api-limit.transport-messages'], [LimitedApi.TRANSPORT_MESSAGES_PER_DEVICE, 'api-limit.transport-messages-per-device'], [LimitedApi.TRANSPORT_MESSAGES_PER_GATEWAY, 'api-limit.transport-messages-per-gateway'], - [LimitedApi.TRANSPORT_MESSAGES_PER_GATEWAY_DEVICE, 'api-limit.transport-messages-per-gateway_device'], + [LimitedApi.TRANSPORT_MESSAGES_PER_GATEWAY_DEVICE, 'api-limit.transport-messages-per-gateway-device'], [LimitedApi.EDGE_EVENTS, 'api-limit.edge-events'], [LimitedApi.EDGE_EVENTS_PER_EDGE, 'api-limit.edge-events-per-edge'], [LimitedApi.EDGE_UPLINK_MESSAGES, 'api-limit.edge-uplink-messages'], diff --git a/ui-ngx/src/assets/locale/locale.constant-ar_AE.json b/ui-ngx/src/assets/locale/locale.constant-ar_AE.json index ec00225e6a..19b5113a24 100644 --- a/ui-ngx/src/assets/locale/locale.constant-ar_AE.json +++ b/ui-ngx/src/assets/locale/locale.constant-ar_AE.json @@ -2000,7 +2000,7 @@ "short-id": "معرف الخادم القصير", "short-id-tooltip": "معرف الخادم القصير. يُستخدم كرابط لربط نموذج كائن الخادم.\nهذا المعرف يُميز بشكل فريد كل خادم LwM2M المُعد للعميل LwM2M.\nيجب ضبط المورد عندما يكون مورد الخادم التمهيدي بقيمة 'false'.\nلا يجب استخدام قيم المعرف ID:0 و ID:65535 لتحديد خادم LwM2M.", "short-id-required": "معرف الخادم القصير مطلوب.", - "short-id-range": "يجب أن يكون معرف الخادم القصير ضمن نطاق من 1 إلى 65534.", + "short-id-range": "يجب أن يكون معرف الخادم القصير ضمن نطاق من {{ min }} إلى {{ max }}.", "short-id-pattern": "يجب أن يكون معرف الخادم القصير عددًا صحيحًا موجبًا.", "lifetime": "مدة تسجيل العميل", "lifetime-required": "مدة تسجيل العميل مطلوبة.", diff --git a/ui-ngx/src/assets/locale/locale.constant-ca_ES.json b/ui-ngx/src/assets/locale/locale.constant-ca_ES.json index b2da56974f..e043a60025 100644 --- a/ui-ngx/src/assets/locale/locale.constant-ca_ES.json +++ b/ui-ngx/src/assets/locale/locale.constant-ca_ES.json @@ -1632,7 +1632,7 @@ "short-id": "Identificador curt del servidor", "short-id-tooltip": "Identificador curt del servidor. S'utilitza com a enllaç a la instància d'objecte del servidor associada.\nAquest identificador identifica de manera única cada servidor LwM2M configurat per al client LwM2M.\nEl recurs S'HA d'establir quan el recurs del servidor Bootstrap té un valor 'fals'.\nEls valors ID:0 i ID :65535 NO S'HAN d'utilitzar per identificar el servidor LwM2M.", "short-id-required": "Cal identificador curt del servidor.", - "short-id-range": "L'identificador de servidor curt hauria d'estar entre 1 i 65534.", + "short-id-range": "L'identificador de servidor curt hauria d'estar entre {{ min }} i {{ max }}.", "short-id-pattern": "L'identificador de servidor curt ha de ser un nombre enter positiu.", "lifetime": "Vida útil del registre del client", "lifetime-required": "Cal vida útil del registre del client.", diff --git a/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json b/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json index f371a19f29..57e19e9faa 100644 --- a/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json +++ b/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json @@ -1247,7 +1247,7 @@ "mode": "Režim konfigurace bezpečnosti", "short-id": "Krátké ID", "short-id-required": "Krátké ID je povinné.", - "short-id-range": "Krátké ID by mělo být v rozsahu od 1 do 65534.", + "short-id-range": "Krátké ID by mělo být v rozsahu od {{ min }} do {{ max }}.", "short-id-pattern": "Krátké ID musí být kladné celé číslo.", "lifetime": "Doba platnosti registrace klienta", "lifetime-required": "Doba platnosti registrace klienta je povinná.", diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 5570b0419d..d3e43fcfbd 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1867,8 +1867,9 @@ "server": "Server", "short-id": "Short server ID", "short-id-tooltip": "Server short Id. Used as link to associate server Object Instance.\nThis identifier uniquely identifies each LwM2M Server configured for the LwM2M Client.\nResource MUST be set when the Bootstrap-Server Resource has a value of 'false'.\nThe values ID:0 and ID:65535 values MUST NOT be used for identifying the LwM2M Server.", + "short-id-tooltip-bootstrap": "Server short Id. Used as link to associate server Object Instance.\nThis identifier uniquely identifies each LwM2M Server configured for the LwM2M Client.\nResource MUST be set when the Bootstrap-Server Resource has a value of 'false'.", "short-id-required": "Short server ID is required.", - "short-id-range": "Short server ID should be in a range from 1 to 65534.", + "short-id-range": "Short server ID should be in a range from {{ min }} to {{ max }}.", "short-id-pattern": "Short server ID must be a positive integer.", "lifetime": "Client registration lifetime", "lifetime-required": "Client registration lifetime is required.", @@ -2842,6 +2843,7 @@ "enable-remote-logging": "Enable remote logging", "ellipsis-chips-text": "+ {{count}} more", "launch-gateway": "Launch gateway", + "launch-command": "Launch command", "launch-docker-compose": "Start the gateway using the following command in the terminal from folder with docker-compose.yml file", "logs-configuration": "Logs configuration", "create-new-gateway": "Create a new gateway", diff --git a/ui-ngx/src/assets/locale/locale.constant-es_ES.json b/ui-ngx/src/assets/locale/locale.constant-es_ES.json index 314a70e7fa..f5f62850b2 100644 --- a/ui-ngx/src/assets/locale/locale.constant-es_ES.json +++ b/ui-ngx/src/assets/locale/locale.constant-es_ES.json @@ -1757,7 +1757,7 @@ "short-id": "Short server ID", "short-id-tooltip": "Id corto del servidor. Usado como enlace para asociar las instancias de objetos del servidor.\nEste identificador sirve para identificar únicamente cada servidor LwM2M configurado para el cliente LwM2M.\nLos recursos DEBEN ser ajustados cuando el servidor Bootstrap tenga un valor de 'false'.\nLos valores ID:0 and ID:65535 NO DEBEN ser usados para identificar al servidor LwM2M.", "short-id-required": "Se requiere Short server ID.", - "short-id-range": "Short server ID debe estar en un rango de 1 a 65534.", + "short-id-range": "Short server ID debe estar en un rango de {{ min }} a {{ max }}.", "short-id-pattern": "Short server ID debe ser un número entero positivo.", "lifetime": "Ciclo de vida registro de cliente (Registration Lifetime)", "lifetime-required": "Se requiere ciclo de vida.", diff --git a/ui-ngx/src/assets/locale/locale.constant-lt_LT.json b/ui-ngx/src/assets/locale/locale.constant-lt_LT.json index 5ca808146c..21338bf1f0 100644 --- a/ui-ngx/src/assets/locale/locale.constant-lt_LT.json +++ b/ui-ngx/src/assets/locale/locale.constant-lt_LT.json @@ -1970,7 +1970,7 @@ "short-id": "Short server ID", "short-id-tooltip": "Server short Id. Used as link to associate server Object Instance.\nThis identifier uniquely identifies each LwM2M Server configured for the LwM2M Client.\nResource MUST be set when the Bootstrap-Server Resource has a value of 'false'.\nThe values ID:0 and ID:65535 values MUST NOT be used for identifying the LwM2M Server.", "short-id-required": "Short server ID is required.", - "short-id-range": "Short server ID should be in a range from 1 to 65534.", + "short-id-range": "Short server ID should be in a range from {{ min }} to {{ max }}.", "short-id-pattern": "Short server ID must be a positive integer.", "lifetime": "Client registration lifetime", "lifetime-required": "Client registration lifetime is required.", diff --git a/ui-ngx/src/assets/locale/locale.constant-nl_BE.json b/ui-ngx/src/assets/locale/locale.constant-nl_BE.json index e8e2cb1f7d..fb736931f4 100644 --- a/ui-ngx/src/assets/locale/locale.constant-nl_BE.json +++ b/ui-ngx/src/assets/locale/locale.constant-nl_BE.json @@ -1857,7 +1857,7 @@ "short-id": "Korte server-ID", "short-id-tooltip": "Server-id kort Id. Wordt gebruikt als koppeling naar het Object-exemplaar van de koppeling.\nDeze id identificeert elke LwM2M-server die is geconfigureerd voor de LwM2M-client op unieke wijze.\nResource MOET worden ingesteld wanneer de Bootstrap-Server Resource een waarde van 'false' heeft.\nDe waarden ID:0 en ID:65535 mogen NIET worden gebruikt voor het identificeren van de LwM2M-server.", "short-id-required": "Een korte server-ID is vereist.", - "short-id-range": "Korte server-ID moet tussen 1 en 65534 liggen.", + "short-id-range": "Korte server-ID moet tussen {{ min }} en {{ max }} liggen.", "short-id-pattern": "Korte server-ID moet een positief geheel getal zijn.", "lifetime": "Levensduur klantregistratie", "lifetime-required": "Levenslange registratie van klanten is vereist.", diff --git a/ui-ngx/src/assets/locale/locale.constant-pl_PL.json b/ui-ngx/src/assets/locale/locale.constant-pl_PL.json index b30d4afc38..82cd3639b4 100644 --- a/ui-ngx/src/assets/locale/locale.constant-pl_PL.json +++ b/ui-ngx/src/assets/locale/locale.constant-pl_PL.json @@ -1976,7 +1976,7 @@ "short-id": "Krótki identyfikator serwera", "short-id-tooltip": "Krótki identyfikator serwera. ", "short-id-required": "Krótki identyfikator serwera jest wymagany.", - "short-id-range": "Krótki identyfikator serwera powinien mieścić się w zakresie od 1 do 65534.", + "short-id-range": "Krótki identyfikator serwera powinien mieścić się w zakresie od {{ min }} do {{ max }}.", "short-id-pattern": "Krótki identyfikator serwera musi być dodatnią liczbą całkowitą.", "lifetime": "Okres rejestracji klienta", "lifetime-required": "Okres rejestracji klienta jest wymagany.", diff --git a/ui-ngx/src/assets/locale/locale.constant-tr_TR.json b/ui-ngx/src/assets/locale/locale.constant-tr_TR.json index a8098a7153..d3e63db882 100644 --- a/ui-ngx/src/assets/locale/locale.constant-tr_TR.json +++ b/ui-ngx/src/assets/locale/locale.constant-tr_TR.json @@ -1260,7 +1260,7 @@ "mode": "Güvenlik yapılandırma modu", "short-id": "Kısa ID", "short-id-required": "Kısa ID gerekli.", - "short-id-range": "Kısa ID 1 ile 65534 aralığında olmalıdır.", + "short-id-range": "Kısa ID {{ min }} ile {{ max }} aralığında olmalıdır.", "short-id-pattern": "Kısa ID pozitif bir tam sayı olmalıdır.", "lifetime": "İstemci kayıt ömrü", "lifetime-required": "İstemci kayıt ömrü gerekli.", diff --git a/ui-ngx/src/assets/locale/locale.constant-zh_CN.json b/ui-ngx/src/assets/locale/locale.constant-zh_CN.json index 99b13168c2..4ae424c843 100644 --- a/ui-ngx/src/assets/locale/locale.constant-zh_CN.json +++ b/ui-ngx/src/assets/locale/locale.constant-zh_CN.json @@ -1794,7 +1794,7 @@ "short-id": "服务器ID", "short-id-tooltip": "服务器ID用作关联服务器对象实例的链接。", "short-id-required": "服务器ID必填。", - "short-id-range": "服务器ID应在1到65534范围内。", + "short-id-range": "服务器ID应在{{ min }}到{{ max }}范围内。", "short-id-pattern": "服务器ID必须是一个正整数。", "lifetime": "客户端注册生命周期", "lifetime-required": "客户端注册生命周期必填。", diff --git a/ui-ngx/src/assets/locale/locale.constant-zh_TW.json b/ui-ngx/src/assets/locale/locale.constant-zh_TW.json index 51f02e7855..68df8adcb1 100644 --- a/ui-ngx/src/assets/locale/locale.constant-zh_TW.json +++ b/ui-ngx/src/assets/locale/locale.constant-zh_TW.json @@ -1432,7 +1432,7 @@ "short-id": "短伺服器ID", "short-id-tooltip": "短伺服器ID。用作關聯伺服器物件實例的鏈接。 \n此標識符唯一標識為LwM2M伺服器客戶端配置的每個LwM2M 伺服器。\n當引導伺服器資源的值為'false'時,必須設置資源。\nID:0值和ID:65535值不得用於識別LwM2M伺服器。.", "short-id-required": "短伺服器ID必填", - "short-id-range": "短伺服器ID長度需介於1到65534。", + "short-id-range": "短伺服器ID長度需介於{{ min }}到{{ max }}。", "short-id-pattern": "短伺服器ID需為正整數", "lifetime": "客戶登記使用期限", "lifetime-required": "客戶登記使用期限必填",