Browse Source

Merge branch 'master' of github.com:thingsboard/thingsboard

pull/5175/head
Andrii Shvaika 5 years ago
parent
commit
0e323bdd77
  1. 6
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  2. 4
      application/src/main/java/org/thingsboard/server/controller/EdgeController.java
  3. 110
      application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeLicenseService.java
  4. 26
      application/src/main/java/org/thingsboard/server/service/edge/EdgeLicenseService.java
  5. 5
      common/dao-api/pom.xml
  6. 6
      common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java
  7. 82
      dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java
  8. 1
      ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts
  9. 7
      ui-ngx/src/app/shared/components/queue/queue-type-list.component.html
  10. 47
      ui-ngx/src/app/shared/components/queue/queue-type-list.component.ts
  11. 5
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  12. 2
      ui-ngx/src/assets/locale/locale.constant-ko_KR.json
  13. 2
      ui-ngx/src/assets/locale/locale.constant-sl_SI.json

6
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -27,6 +27,7 @@ import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.DashboardInfo;
@ -122,12 +123,12 @@ import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.action.RuleEngineEntityActionService;
import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.edge.EdgeLicenseService;
import org.thingsboard.server.service.edge.EdgeNotificationService;
import org.thingsboard.server.service.edge.rpc.EdgeRpcService;
import org.thingsboard.server.service.lwm2m.LwM2MServerSecurityInfoRepository;
import org.thingsboard.server.service.ota.OtaPackageStateService;
import org.thingsboard.server.service.profile.TbDeviceProfileCache;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.service.resource.TbResourceService;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.AccessControlService;
@ -274,6 +275,9 @@ public abstract class BaseController {
@Autowired(required = false)
protected EdgeRpcService edgeGrpcService;
@Autowired(required = false)
protected EdgeLicenseService edgeLicenseService;
@Autowired
protected RuleEngineEntityActionService ruleEngineEntityActionService;

4
application/src/main/java/org/thingsboard/server/controller/EdgeController.java

@ -572,7 +572,7 @@ public class EdgeController extends BaseController {
public ResponseEntity<JsonNode> checkInstance(@RequestBody JsonNode request) throws ThingsboardException {
log.debug("Checking instance [{}]", request);
try {
return edgeService.checkInstance(request);
return edgeLicenseService.checkInstance(request);
} catch (Exception e) {
log.error("Error occurred: [{}]", e.getMessage(), e);
throw new ThingsboardException(e, ThingsboardErrorCode.SUBSCRIPTION_VIOLATION);
@ -585,7 +585,7 @@ public class EdgeController extends BaseController {
@RequestParam String releaseDate) throws ThingsboardException {
log.debug("Activating instance [{}], [{}]", licenseSecret, releaseDate);
try {
return edgeService.activateInstance(licenseSecret, releaseDate);
return edgeLicenseService.activateInstance(licenseSecret, releaseDate);
} catch (Exception e) {
log.error("Error occurred: [{}]", e.getMessage(), e);
throw new ThingsboardException(e, ThingsboardErrorCode.SUBSCRIPTION_VIOLATION);

110
application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeLicenseService.java

@ -0,0 +1,110 @@
/**
* Copyright © 2016-2021 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.service.edge;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.thingsboard.server.queue.util.TbCoreComponent;
import javax.annotation.PostConstruct;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.HashMap;
import java.util.Map;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
@Service
@TbCoreComponent
@Slf4j
public class DefaultEdgeLicenseService implements EdgeLicenseService {
private RestTemplate restTemplate;
private static final String EDGE_LICENSE_SERVER_ENDPOINT = "https://license.thingsboard.io";
@Value("${edges.enabled:false}")
private boolean edgesEnabled;
@PostConstruct
public void init() {
if (edgesEnabled) {
initRestTemplate();
}
}
@Override
public ResponseEntity<JsonNode> checkInstance(JsonNode request) {
return this.restTemplate.postForEntity(EDGE_LICENSE_SERVER_ENDPOINT + "/api/license/checkInstance", request, JsonNode.class);
}
@Override
public ResponseEntity<JsonNode> activateInstance(String edgeLicenseSecret, String releaseDate) {
Map<String, String> params = new HashMap<>();
params.put("licenseSecret", edgeLicenseSecret);
params.put("releaseDate", releaseDate);
return this.restTemplate.postForEntity(EDGE_LICENSE_SERVER_ENDPOINT + "/api/license/activateInstance?licenseSecret={licenseSecret}&releaseDate={releaseDate}", null, JsonNode.class, params);
}
private void initRestTemplate() {
boolean jdkHttpClientEnabled = isNotEmpty(System.getProperty("tb.proxy.jdk")) && System.getProperty("tb.proxy.jdk").equalsIgnoreCase("true");
boolean systemProxyEnabled = isNotEmpty(System.getProperty("tb.proxy.system")) && System.getProperty("tb.proxy.system").equalsIgnoreCase("true");
boolean proxyEnabled = isNotEmpty(System.getProperty("tb.proxy.host")) && isNotEmpty(System.getProperty("tb.proxy.port"));
if (jdkHttpClientEnabled) {
log.warn("Going to use plain JDK Http Client!");
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
if (proxyEnabled) {
log.warn("Going to use Proxy Server: [{}:{}]", System.getProperty("tb.proxy.host"), System.getProperty("tb.proxy.port"));
factory.setProxy(new Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved(System.getProperty("tb.proxy.host"), Integer.parseInt(System.getProperty("tb.proxy.port")))));
}
this.restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory());
} else {
CloseableHttpClient httpClient;
HttpComponentsClientHttpRequestFactory requestFactory;
if (systemProxyEnabled) {
log.warn("Going to use System Proxy Server!");
httpClient = HttpClients.createSystem();
requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
this.restTemplate = new RestTemplate(requestFactory);
} else if (proxyEnabled) {
log.warn("Going to use Proxy Server: [{}:{}]", System.getProperty("tb.proxy.host"), System.getProperty("tb.proxy.port"));
httpClient = HttpClients.custom().setSSLHostnameVerifier(new DefaultHostnameVerifier()).setProxy(new HttpHost(System.getProperty("tb.proxy.host"), Integer.parseInt(System.getProperty("tb.proxy.port")), "https")).build();
requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
this.restTemplate = new RestTemplate(requestFactory);
} else {
httpClient = HttpClients.custom().setSSLHostnameVerifier(new DefaultHostnameVerifier()).build();
requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
this.restTemplate = new RestTemplate(requestFactory);
}
}
}
}

26
application/src/main/java/org/thingsboard/server/service/edge/EdgeLicenseService.java

@ -0,0 +1,26 @@
/**
* Copyright © 2016-2021 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.service.edge;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.http.ResponseEntity;
public interface EdgeLicenseService {
ResponseEntity<JsonNode> checkInstance(JsonNode request);
ResponseEntity<JsonNode> activateInstance(String licenseSecret, String releaseDate);
}

5
common/dao-api/pom.xml

@ -85,11 +85,6 @@
<artifactId>spring-boot-autoconfigure</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-core</artifactId>

6
common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java

@ -15,9 +15,7 @@
*/
package org.thingsboard.server.dao.edge;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.util.concurrent.ListenableFuture;
import org.springframework.http.ResponseEntity;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeInfo;
@ -86,9 +84,5 @@ public interface EdgeService {
PageData<EdgeId> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId, PageLink pageLink);
ResponseEntity<JsonNode> checkInstance(JsonNode request);
ResponseEntity<JsonNode> activateInstance(String licenseSecret, String releaseDate);
String findMissingToRelatedRuleChains(TenantId tenantId, EdgeId edgeId);
}

82
dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java

@ -15,7 +15,6 @@
*/
package org.thingsboard.server.dao.edge;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
@ -24,23 +23,14 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
@ -74,20 +64,14 @@ import org.thingsboard.server.dao.tenant.TenantDao;
import org.thingsboard.server.dao.user.UserService;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import static org.thingsboard.server.common.data.CacheConstants.EDGE_CACHE;
import static org.thingsboard.server.dao.DaoUtil.toUUIDs;
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
@ -108,10 +92,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic
private static final int DEFAULT_PAGE_SIZE = 1000;
private RestTemplate restTemplate;
private static final String EDGE_LICENSE_SERVER_ENDPOINT = "https://license.thingsboard.io";
@Autowired
private EdgeDao edgeDao;
@ -133,16 +113,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic
@Autowired
private RelationService relationService;
@Value("${edges.enabled:false}")
private boolean edgesEnabled;
@PostConstruct
public void init() {
if (edgesEnabled) {
initRestTemplate();
}
}
@Override
public Edge findEdgeById(TenantId tenantId, EdgeId edgeId) {
log.trace("Executing findEdgeById [{}]", edgeId);
@ -544,19 +514,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic
return new PageData<>(edgeIds, pageData.getTotalPages(), pageData.getTotalElements(), pageData.hasNext());
}
@Override
public ResponseEntity<JsonNode> checkInstance(JsonNode request) {
return this.restTemplate.postForEntity(EDGE_LICENSE_SERVER_ENDPOINT + "/api/license/checkInstance", request, JsonNode.class);
}
@Override
public ResponseEntity<JsonNode> activateInstance(String edgeLicenseSecret, String releaseDate) {
Map<String, String> params = new HashMap<>();
params.put("licenseSecret", edgeLicenseSecret);
params.put("releaseDate", releaseDate);
return this.restTemplate.postForEntity(EDGE_LICENSE_SERVER_ENDPOINT + "/api/license/activateInstance?licenseSecret={licenseSecret}&releaseDate={releaseDate}", null, JsonNode.class, params);
}
@Override
public String findMissingToRelatedRuleChains(TenantId tenantId, EdgeId edgeId) {
List<RuleChain> edgeRuleChains = findEdgeRuleChains(tenantId, edgeId);
@ -602,43 +559,4 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic
} while (pageData != null && pageData.hasNext());
return result;
}
private void initRestTemplate() {
boolean jdkHttpClientEnabled = isNotEmpty(System.getProperty("tb.proxy.jdk")) && System.getProperty("tb.proxy.jdk").equalsIgnoreCase("true");
boolean systemProxyEnabled = isNotEmpty(System.getProperty("tb.proxy.system")) && System.getProperty("tb.proxy.system").equalsIgnoreCase("true");
boolean proxyEnabled = isNotEmpty(System.getProperty("tb.proxy.host")) && isNotEmpty(System.getProperty("tb.proxy.port"));
if (jdkHttpClientEnabled) {
log.warn("Going to use plain JDK Http Client!");
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
if (proxyEnabled) {
log.warn("Going to use Proxy Server: [{}:{}]", System.getProperty("tb.proxy.host"), System.getProperty("tb.proxy.port"));
factory.setProxy(new Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved(System.getProperty("tb.proxy.host"), Integer.parseInt(System.getProperty("tb.proxy.port")))));
}
this.restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory());
} else {
CloseableHttpClient httpClient;
HttpComponentsClientHttpRequestFactory requestFactory;
if (systemProxyEnabled) {
log.warn("Going to use System Proxy Server!");
httpClient = HttpClients.createSystem();
requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
this.restTemplate = new RestTemplate(requestFactory);
} else if (proxyEnabled) {
log.warn("Going to use Proxy Server: [{}:{}]", System.getProperty("tb.proxy.host"), System.getProperty("tb.proxy.port"));
httpClient = HttpClients.custom().setSSLHostnameVerifier(new DefaultHostnameVerifier()).setProxy(new HttpHost(System.getProperty("tb.proxy.host"), Integer.parseInt(System.getProperty("tb.proxy.port")), "https")).build();
requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
this.restTemplate = new RestTemplate(requestFactory);
} else {
httpClient = HttpClients.custom().setSSLHostnameVerifier(new DefaultHostnameVerifier()).build();
requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
this.restTemplate = new RestTemplate(requestFactory);
}
}
}
}

1
ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts

@ -289,6 +289,7 @@ export class DeviceWizardDialogComponent extends
const deviceProfile: DeviceProfile = {
name: this.deviceWizardFormGroup.get('newDeviceProfileTitle').value,
type: DeviceProfileType.DEFAULT,
defaultQueueName: this.deviceWizardFormGroup.get('defaultQueueName').value,
transportType: this.transportConfigFormGroup.get('transportType').value,
provisionType: deviceProvisionConfiguration.type,
provisionDeviceKey,

7
ui-ngx/src/app/shared/components/queue/queue-type-list.component.html

@ -34,7 +34,12 @@
#queueAutocomplete="matAutocomplete"
[displayWith]="displayQueueFn">
<mat-option *ngFor="let queue of filteredQueues | async" [value]="queue">
<span [innerHTML]="queue | highlight:searchText"></span>
<span [innerHTML]="queue.queueName | highlight:searchText"></span>
</mat-option>
<mat-option *ngIf="!(filteredQueues | async)?.length" [value]="null">
<span>
{{ translate.get('queue.no-queues-matching', {queue: searchText}) | async }}
</span>
</mat-option>
</mat-autocomplete>
<mat-error *ngIf="queueFormGroup.get('queue').hasError('required')">

47
ui-ngx/src/app/shared/components/queue/queue-type-list.component.ts

@ -34,6 +34,10 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { QueueService } from '@core/http/queue.service';
import { ServiceType } from '@shared/models/queue.models';
interface Queue {
queueName: string;
}
@Component({
selector: 'tb-queue-type-list',
templateUrl: './queue-type-list.component.html',
@ -48,7 +52,7 @@ export class QueueTypeListComponent implements ControlValueAccessor, OnInit, Aft
queueFormGroup: FormGroup;
modelValue: string | null;
modelValue: Queue | null;
private requiredValue: boolean;
get required(): boolean {
@ -67,9 +71,9 @@ export class QueueTypeListComponent implements ControlValueAccessor, OnInit, Aft
@ViewChild('queueInput', {static: true}) queueInput: ElementRef<HTMLInputElement>;
filteredQueues: Observable<Array<string>>;
filteredQueues: Observable<Array<Queue>>;
queues: Observable<Array<string>>;
queues: Observable<Array<Queue>>;
searchText = '';
@ -99,9 +103,15 @@ export class QueueTypeListComponent implements ControlValueAccessor, OnInit, Aft
debounceTime(150),
distinctUntilChanged(),
tap(value => {
this.updateView(value);
let modelValue;
if (typeof value === 'string' || !value) {
modelValue = null;
} else {
modelValue = value;
}
this.updateView(modelValue);
}),
map(value => value ? value : ''),
map(value => value ? (typeof value === 'string' ? value : value.queueName) : ''),
switchMap(queue => this.fetchQueues(queue) )
);
}
@ -123,8 +133,8 @@ export class QueueTypeListComponent implements ControlValueAccessor, OnInit, Aft
writeValue(value: string | null): void {
this.searchText = '';
this.modelValue = value;
this.queueFormGroup.get('queue').patchValue(value, {emitEvent: false});
this.modelValue = value ? { queueName: value } : null;
this.queueFormGroup.get('queue').patchValue(this.modelValue, {emitEvent: false});
this.dirty = true;
}
@ -135,37 +145,42 @@ export class QueueTypeListComponent implements ControlValueAccessor, OnInit, Aft
}
}
updateView(value: string | null) {
updateView(value: Queue | null) {
if (this.modelValue !== value) {
this.modelValue = value;
this.propagateChange(this.modelValue);
this.propagateChange(this.modelValue ? this.modelValue.queueName : null);
}
}
displayQueueFn(queue?: string): string | undefined {
return queue ? queue : undefined;
displayQueueFn(queue?: Queue): string | undefined {
return queue ? queue.queueName : undefined;
}
fetchQueues(searchText?: string): Observable<Array<string>> {
fetchQueues(searchText?: string): Observable<Array<Queue>> {
this.searchText = searchText;
return this.getQueues().pipe(
catchError(() => of([])),
catchError(() => of([] as Array<Queue>)),
map(queues => {
const result = queues.filter( queue => {
return searchText ? queue.toUpperCase().startsWith(searchText.toUpperCase()) : true;
return searchText ? queue.queueName.toUpperCase().startsWith(searchText.toUpperCase()) : true;
});
if (result.length) {
result.sort();
result.sort((q1, q2) => q1.queueName.localeCompare(q2.queueName));
}
return result;
})
);
}
getQueues(): Observable<Array<string>> {
getQueues(): Observable<Array<Queue>> {
if (!this.queues) {
this.queues = this.queueService.
getTenantQueuesByServiceType(this.queueType, {ignoreLoading: true}).pipe(
map((queues) => {
return queues.map((queueName) => {
return { queueName };
});
}),
publishReplay(1),
refCount()
);

5
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1082,7 +1082,7 @@
"default-rule-chain": "Default rule chain",
"mobile-dashboard": "Mobile dashboard",
"mobile-dashboard-hint": "Used by mobile application as a device details dashboard",
"select-queue-hint": "Select from a drop-down list or add a custom name.",
"select-queue-hint": "Select from a drop-down list.",
"delete-device-profile-title": "Are you sure you want to delete the device profile '{{deviceProfileName}}'?",
"delete-device-profile-text": "Be careful, after the confirmation the device profile and all related data will become unrecoverable.",
"delete-device-profiles-title": "Are you sure you want to delete { count, plural, 1 {1 device profile} other {# device profiles} }?",
@ -2570,7 +2570,8 @@
"queue": {
"select_name": "Select queue name",
"name": "Queue Name",
"name_required": "Queue name is required!"
"name_required": "Queue name is required!",
"no-queues-matching": "No queues matching '{{queue}}' were found."
},
"tenant": {
"tenant": "Tenant",

2
ui-ngx/src/assets/locale/locale.constant-ko_KR.json

@ -959,7 +959,7 @@
"profile-configuration": "프로파일 설정",
"transport-configuration": "전송 설정",
"default-rule-chain": "기본 규칙 사슬",
"select-queue-hint": "Select from a drop-down list or add a custom name.",
"select-queue-hint": "Select from a drop-down list.",
"delete-device-profile-title": "Are you sure you want to delete the device profile '{{deviceProfileName}}'?",
"delete-device-profile-text": "Be careful, after the confirmation the device profile and all related data will become unrecoverable.",
"delete-device-profiles-title": "Are you sure you want to delete { count, plural, 1 {1 개 장치 프로파일} other {# 개 장치 프로파일} }?",

2
ui-ngx/src/assets/locale/locale.constant-sl_SI.json

@ -959,7 +959,7 @@
"profile-configuration": "Profile configuration",
"transport-configuration": "Transport configuration",
"default-rule-chain": "Default rule chain",
"select-queue-hint": "Select from a drop-down list or add a custom name.",
"select-queue-hint": "Select from a drop-down list.",
"delete-device-profile-title": "Are you sure you want to delete the device profile '{{deviceProfileName}}'?",
"delete-device-profile-text": "Be careful, after the confirmation the device profile and all related data will become unrecoverable.",
"delete-device-profiles-title": "Are you sure you want to delete { count, plural, 1 {1 device profile} other {# device profiles} }?",

Loading…
Cancel
Save