Merge branch 'develop/3.4' of github.com:thingsboard/thingsboard into fix_bug_import_rulechain

This commit is contained in:
Yuriy Lytvynchuk 2022-07-12 19:06:05 +03:00
commit 915ad7c0fa
34 changed files with 17 additions and 114 deletions

View File

@ -71,3 +71,5 @@ CREATE TABLE IF NOT EXISTS user_auth_settings (
);
CREATE INDEX IF NOT EXISTS idx_api_usage_state_entity_id ON api_usage_state(entity_id);
ALTER TABLE tenant_profile DROP COLUMN IF EXISTS isolated_tb_core;

View File

@ -128,7 +128,6 @@ public class TenantProfileController extends BaseController {
"{\n" +
" \"name\": \"Default\",\n" +
" \"description\": \"Default tenant profile\",\n" +
" \"isolatedTbCore\": false,\n" +
" \"isolatedTbRuleEngine\": false,\n" +
" \"profileData\": {\n" +
" \"configuration\": {\n" +

View File

@ -195,22 +195,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
public void createDefaultTenantProfiles() throws Exception {
tenantProfileService.findOrCreateDefaultTenantProfile(TenantId.SYS_TENANT_ID);
TenantProfileData tenantProfileData = new TenantProfileData();
tenantProfileData.setConfiguration(new DefaultTenantProfileConfiguration());
TenantProfile isolatedTbCoreProfile = new TenantProfile();
isolatedTbCoreProfile.setDefault(false);
isolatedTbCoreProfile.setName("Isolated TB Core");
isolatedTbCoreProfile.setDescription("Isolated TB Core tenant profile");
isolatedTbCoreProfile.setIsolatedTbCore(true);
isolatedTbCoreProfile.setIsolatedTbRuleEngine(false);
isolatedTbCoreProfile.setProfileData(tenantProfileData);
try {
tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, isolatedTbCoreProfile);
} catch (DataValidationException e) {
log.warn(e.getMessage());
}
TenantProfileData isolatedRuleEngineTenantProfileData = new TenantProfileData();
isolatedRuleEngineTenantProfileData.setConfiguration(new DefaultTenantProfileConfiguration());
@ -239,7 +223,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
isolatedTbRuleEngineProfile.setDefault(false);
isolatedTbRuleEngineProfile.setName("Isolated TB Rule Engine");
isolatedTbRuleEngineProfile.setDescription("Isolated TB Rule Engine tenant profile");
isolatedTbRuleEngineProfile.setIsolatedTbCore(false);
isolatedTbRuleEngineProfile.setIsolatedTbRuleEngine(true);
isolatedTbRuleEngineProfile.setProfileData(isolatedRuleEngineTenantProfileData);
@ -248,20 +231,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
} catch (DataValidationException e) {
log.warn(e.getMessage());
}
TenantProfile isolatedTbCoreAndTbRuleEngineProfile = new TenantProfile();
isolatedTbCoreAndTbRuleEngineProfile.setDefault(false);
isolatedTbCoreAndTbRuleEngineProfile.setName("Isolated TB Core and TB Rule Engine");
isolatedTbCoreAndTbRuleEngineProfile.setDescription("Isolated TB Core and TB Rule Engine tenant profile");
isolatedTbCoreAndTbRuleEngineProfile.setIsolatedTbCore(true);
isolatedTbCoreAndTbRuleEngineProfile.setIsolatedTbRuleEngine(true);
isolatedTbCoreAndTbRuleEngineProfile.setProfileData(isolatedRuleEngineTenantProfileData);
try {
tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, isolatedTbCoreAndTbRuleEngineProfile);
} catch (DataValidationException e) {
log.warn(e.getMessage());
}
}
@Override

View File

@ -45,7 +45,7 @@ public class DefaultTenantRoutingInfoService implements TenantRoutingInfoService
Tenant tenant = tenantService.findTenantById(tenantId);
if (tenant != null) {
TenantProfile tenantProfile = tenantProfileCache.get(tenant.getTenantProfileId());
return new TenantRoutingInfo(tenantId, tenantProfile.isIsolatedTbCore(), tenantProfile.isIsolatedTbRuleEngine());
return new TenantRoutingInfo(tenantId, tenantProfile.isIsolatedTbRuleEngine());
} else {
throw new RuntimeException("Tenant not found!");
}

View File

@ -148,7 +148,7 @@ ui:
# Help parameters
help:
# Base url for UI help assets
base-url: "${UI_HELP_BASE_URL:https://raw.githubusercontent.com/thingsboard/thingsboard-ui-help/release-3.3.4}"
base-url: "${UI_HELP_BASE_URL:https://raw.githubusercontent.com/thingsboard/thingsboard-ui-help/release-3.4}"
database:
ts_max_intervals: "${DATABASE_TS_MAX_INTERVALS:700}" # Max number of DB queries generated by single API call to fetch telemetry records

View File

@ -66,7 +66,6 @@ public abstract class BaseTenantProfileControllerTest extends AbstractController
Assert.assertEquals(tenantProfile.getDescription(), savedTenantProfile.getDescription());
Assert.assertEquals(tenantProfile.getProfileData(), savedTenantProfile.getProfileData());
Assert.assertEquals(tenantProfile.isDefault(), savedTenantProfile.isDefault());
Assert.assertEquals(tenantProfile.isIsolatedTbCore(), savedTenantProfile.isIsolatedTbCore());
Assert.assertEquals(tenantProfile.isIsolatedTbRuleEngine(), savedTenantProfile.isIsolatedTbRuleEngine());
testBroadcastEntityStateChangeEventTimeManyTimeTenantProfile(savedTenantProfile, ComponentLifecycleEvent.CREATED, 1);
@ -182,22 +181,6 @@ public abstract class BaseTenantProfileControllerTest extends AbstractController
testBroadcastEntityStateChangeEventNeverTenantProfile();
}
@Test
public void testSaveSameTenantProfileWithDifferentIsolatedTbCore() throws Exception {
loginSysAdmin();
TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
TenantProfile savedTenantProfile = doPost("/api/tenantProfile", tenantProfile, TenantProfile.class);
Mockito.reset(tbClusterService);
savedTenantProfile.setIsolatedTbCore(true);
doPost("/api/tenantProfile", savedTenantProfile)
.andExpect(status().isBadRequest())
.andExpect(statusReason(containsString("Can't update isolatedTbCore property")));
testBroadcastEntityStateChangeEventNeverTenantProfile();
}
@Test
public void testDeleteTenantProfileWithExistingTenant() throws Exception {
loginSysAdmin();
@ -352,7 +335,6 @@ public abstract class BaseTenantProfileControllerTest extends AbstractController
tenantProfileData.setConfiguration(new DefaultTenantProfileConfiguration());
tenantProfile.setProfileData(tenantProfileData);
tenantProfile.setDefault(false);
tenantProfile.setIsolatedTbCore(false);
tenantProfile.setIsolatedTbRuleEngine(false);
return tenantProfile;
}

View File

@ -273,7 +273,6 @@ message GetTenantRoutingInfoRequestMsg {
}
message GetTenantRoutingInfoResponseMsg {
bool isolatedTbCore = 1;
bool isolatedTbRuleEngine = 2;
}

View File

@ -53,13 +53,10 @@ public class TenantProfile extends SearchTextBased<TenantProfileId> implements H
private String description;
@ApiModelProperty(position = 5, value = "Default Tenant profile to be used.", example = "true")
private boolean isDefault;
@ApiModelProperty(position = 6, value = "If enabled, will push all messages related to this tenant and processed by core platform services into separate queue. " +
"Useful for complex microservices deployments, to isolate processing of the data for specific tenants", example = "true")
private boolean isolatedTbCore;
@ApiModelProperty(position = 7, value = "If enabled, will push all messages related to this tenant and processed by the rule engine into separate queue. " +
@ApiModelProperty(position = 6, value = "If enabled, will push all messages related to this tenant and processed by the rule engine into separate queue. " +
"Useful for complex microservices deployments, to isolate processing of the data for specific tenants", example = "true")
private boolean isolatedTbRuleEngine;
@ApiModelProperty(position = 8, value = "Complex JSON object that contains profile settings: queue configs, max devices, max assets, rate limits, etc.")
@ApiModelProperty(position = 7, value = "Complex JSON object that contains profile settings: queue configs, max devices, max assets, rate limits, etc.")
private transient TenantProfileData profileData;
@JsonIgnore
private byte[] profileDataBytes;
@ -77,7 +74,6 @@ public class TenantProfile extends SearchTextBased<TenantProfileId> implements H
this.name = tenantProfile.getName();
this.description = tenantProfile.getDescription();
this.isDefault = tenantProfile.isDefault();
this.isolatedTbCore = tenantProfile.isIsolatedTbCore();
this.isolatedTbRuleEngine = tenantProfile.isIsolatedTbRuleEngine();
this.setProfileData(tenantProfile.getProfileData());
}

View File

@ -365,8 +365,6 @@ public class HashPartitionService implements PartitionService {
throw new RuntimeException("Tenant not found!");
}
switch (serviceType) {
case TB_CORE:
return routingInfo.isIsolatedTbCore();
case TB_RULE_ENGINE:
return routingInfo.isIsolatedTbRuleEngine();
default:

View File

@ -21,6 +21,5 @@ import org.thingsboard.server.common.data.id.TenantId;
@Data
public class TenantRoutingInfo {
private final TenantId tenantId;
private final boolean isolatedTbCore;
private final boolean isolatedTbRuleEngine;
}

View File

@ -38,7 +38,7 @@ public class TransportTenantRoutingInfoService implements TenantRoutingInfoServi
@Override
public TenantRoutingInfo getRoutingInfo(TenantId tenantId) {
TenantProfile profile = tenantProfileCache.get(tenantId);
return new TenantRoutingInfo(tenantId, profile.isIsolatedTbCore(), profile.isIsolatedTbRuleEngine());
return new TenantRoutingInfo(tenantId, profile.isIsolatedTbRuleEngine());
}
}

View File

@ -53,9 +53,6 @@ public final class TenantProfileEntity extends BaseSqlEntity<TenantProfile> impl
@Column(name = ModelConstants.TENANT_PROFILE_IS_DEFAULT_PROPERTY)
private boolean isDefault;
@Column(name = ModelConstants.TENANT_PROFILE_ISOLATED_TB_CORE)
private boolean isolatedTbCore;
@Column(name = ModelConstants.TENANT_PROFILE_ISOLATED_TB_RULE_ENGINE)
private boolean isolatedTbRuleEngine;
@ -75,7 +72,6 @@ public final class TenantProfileEntity extends BaseSqlEntity<TenantProfile> impl
this.name = tenantProfile.getName();
this.description = tenantProfile.getDescription();
this.isDefault = tenantProfile.isDefault();
this.isolatedTbCore = tenantProfile.isIsolatedTbCore();
this.isolatedTbRuleEngine = tenantProfile.isIsolatedTbRuleEngine();
this.profileData = JacksonUtil.convertValue(tenantProfile.getProfileData(), ObjectNode.class);
}
@ -101,7 +97,6 @@ public final class TenantProfileEntity extends BaseSqlEntity<TenantProfile> impl
tenantProfile.setName(name);
tenantProfile.setDescription(description);
tenantProfile.setDefault(isDefault);
tenantProfile.setIsolatedTbCore(isolatedTbCore);
tenantProfile.setIsolatedTbRuleEngine(isolatedTbRuleEngine);
tenantProfile.setProfileData(JacksonUtil.convertValue(profileData, TenantProfileData.class));
return tenantProfile;

View File

@ -100,8 +100,6 @@ public class TenantProfileDataValidator extends DataValidator<TenantProfile> {
throw new DataValidationException("Can't update non existing tenant profile!");
} else if (old.isIsolatedTbRuleEngine() != tenantProfile.isIsolatedTbRuleEngine()) {
throw new DataValidationException("Can't update isolatedTbRuleEngine property!");
} else if (old.isIsolatedTbCore() != tenantProfile.isIsolatedTbCore()) {
throw new DataValidationException("Can't update isolatedTbCore property!");
}
return old;
}

View File

@ -153,7 +153,6 @@ public class TenantProfileServiceImpl extends AbstractCachedEntityService<Tenant
profileData.setConfiguration(new DefaultTenantProfileConfiguration());
defaultTenantProfile.setProfileData(profileData);
defaultTenantProfile.setDescription("Default tenant profile");
defaultTenantProfile.setIsolatedTbCore(false);
defaultTenantProfile.setIsolatedTbRuleEngine(false);
defaultTenantProfile = saveTenantProfile(tenantId, defaultTenantProfile);
}

View File

@ -51,7 +51,6 @@ public abstract class BaseQueueServiceTest extends AbstractServiceTest {
tenantProfile.setDefault(false);
tenantProfile.setName("Isolated TB Rule Engine");
tenantProfile.setDescription("Isolated TB Rule Engine tenant profile");
tenantProfile.setIsolatedTbCore(false);
tenantProfile.setIsolatedTbRuleEngine(true);
TenantProfileQueueConfiguration mainQueueConfiguration = new TenantProfileQueueConfiguration();

View File

@ -85,7 +85,6 @@ public abstract class BaseTenantProfileServiceTest extends AbstractServiceTest {
Assert.assertEquals(tenantProfile.getDescription(), savedTenantProfile.getDescription());
Assert.assertEquals(tenantProfile.getProfileData(), savedTenantProfile.getProfileData());
Assert.assertEquals(tenantProfile.isDefault(), savedTenantProfile.isDefault());
Assert.assertEquals(tenantProfile.isIsolatedTbCore(), savedTenantProfile.isIsolatedTbCore());
Assert.assertEquals(tenantProfile.isIsolatedTbRuleEngine(), savedTenantProfile.isIsolatedTbRuleEngine());
savedTenantProfile.setName("New tenant profile");
@ -177,14 +176,6 @@ public abstract class BaseTenantProfileServiceTest extends AbstractServiceTest {
tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile);
}
@Test(expected = DataValidationException.class)
public void testSaveSameTenantProfileWithDifferentIsolatedTbCore() {
TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
savedTenantProfile.setIsolatedTbCore(true);
tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile);
}
@Test(expected = DataValidationException.class)
public void testDeleteTenantProfileWithExistingTenant() {
TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
@ -298,7 +289,6 @@ public abstract class BaseTenantProfileServiceTest extends AbstractServiceTest {
profileData.setConfiguration(new DefaultTenantProfileConfiguration());
tenantProfile.setProfileData(profileData);
tenantProfile.setDefault(false);
tenantProfile.setIsolatedTbCore(false);
tenantProfile.setIsolatedTbRuleEngine(false);
return tenantProfile;
}

View File

@ -309,7 +309,6 @@ public abstract class BaseTenantServiceTest extends AbstractServiceTest {
profileData.setConfiguration(new DefaultTenantProfileConfiguration());
tenantProfile.setProfileData(profileData);
tenantProfile.setDefault(false);
tenantProfile.setIsolatedTbCore(true);
tenantProfile.setIsolatedTbRuleEngine(true);
TenantProfile isolatedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);

View File

@ -25,6 +25,6 @@ public class VersionControlTenantRoutingInfoService implements TenantRoutingInfo
@Override
public TenantRoutingInfo getRoutingInfo(TenantId tenantId) {
//This dummy implementation is ok since Version Control service does not produce any rule engine messages.
return new TenantRoutingInfo(tenantId, false, false);
return new TenantRoutingInfo(tenantId, false);
}
}

View File

@ -631,7 +631,6 @@ export class ImportExportService {
private validateImportedTenantProfile(tenantProfile: TenantProfile): boolean {
return isDefined(tenantProfile.name)
&& isDefined(tenantProfile.profileData)
&& isDefined(tenantProfile.isolatedTbCore)
&& isDefined(tenantProfile.isolatedTbRuleEngine);
}

View File

@ -59,10 +59,6 @@
</mat-error>
</mat-form-field>
<div fxLayout="column">
<mat-checkbox class="hinted-checkbox" formControlName="isolatedTbCore">
<div>{{ 'tenant.isolated-tb-core' | translate }}</div>
<div class="tb-hint">{{'tenant.isolated-tb-core-details' | translate}}</div>
</mat-checkbox>
<mat-checkbox class="hinted-checkbox" formControlName="isolatedTbRuleEngine">
<div>{{ 'tenant.isolated-tb-rule-engine' | translate }}</div>
<div class="tb-hint">{{'tenant.isolated-tb-rule-engine-details' | translate}}</div>

View File

@ -81,7 +81,6 @@ export class TenantProfileComponent extends EntityComponent<TenantProfile> {
const formGroup = this.fb.group(
{
name: [entity ? entity.name : '', [Validators.required, Validators.maxLength(255)]],
isolatedTbCore: [entity ? entity.isolatedTbCore : false, []],
isolatedTbRuleEngine: [entity ? entity.isolatedTbRuleEngine : false, []],
profileData: this.fb.group({
configuration: [entity && !this.isAdd ? entity?.profileData.configuration
@ -107,7 +106,6 @@ export class TenantProfileComponent extends EntityComponent<TenantProfile> {
updateForm(entity: TenantProfile) {
this.entityForm.patchValue({name: entity.name}, {emitEvent: false});
this.entityForm.patchValue({isolatedTbCore: entity.isolatedTbCore}, {emitEvent: false});
this.entityForm.patchValue({isolatedTbRuleEngine: entity.isolatedTbRuleEngine}, {emitEvent: false});
this.entityForm.get('profileData').patchValue({
configuration: !this.isAdd ? entity.profileData?.configuration : createTenantProfileConfiguration(TenantProfileType.DEFAULT)
@ -121,7 +119,6 @@ export class TenantProfileComponent extends EntityComponent<TenantProfile> {
if (this.isEditValue) {
this.entityForm.enable({emitEvent: false});
if (!this.isAdd) {
this.entityForm.get('isolatedTbCore').disable({emitEvent: false});
this.entityForm.get('isolatedTbRuleEngine').disable({emitEvent: false});
}
} else {

View File

@ -25,7 +25,8 @@
'tb-highlighted': isHighlighted(widget),
'tb-not-highlighted': isNotHighlighted(widget),
'mat-elevation-z4': widget.dropShadow,
'tb-has-timewindow': widget.hasTimewindow
'tb-has-timewindow': widget.hasTimewindow,
'tb-edit': isEdit
}"
[ngStyle]="widget.style"
(mousedown)="onMouseDown($event)"

View File

@ -114,4 +114,8 @@ div.tb-widget {
&.tb-not-highlighted {
opacity: .5;
}
&.tb-edit {
cursor: pointer;
}
}

View File

@ -428,7 +428,7 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
this.hasAggregation = this.widget.type === widgetType.timeseries;
this.style = {cursor: 'pointer',
this.style = {
color: this.color,
backgroundColor: this.backgroundColor,
padding: this.padding,

View File

@ -126,11 +126,11 @@ export class TbMarkdownComponent implements OnChanges {
this.handlePlugins(this.tbMarkdownInstanceComponentRef.location.nativeElement);
this.markdownService.highlight(this.tbMarkdownInstanceComponentRef.location.nativeElement);
readyObservable = this.handleImages(this.tbMarkdownInstanceComponentRef.location.nativeElement);
this.cd.detectChanges();
this.error = null;
} catch (error) {
readyObservable = this.handleError(compiled, error);
}
this.cd.detectChanges();
readyObservable.subscribe(() => {
this.ready.emit();
});
@ -146,9 +146,8 @@ export class TbMarkdownComponent implements OnChanges {
private handleError(template: string, error): Observable<void> {
this.error = (error ? error + '' : 'Failed to render markdown!').replace(/\n/g, '<br>');
this.destroyMarkdownInstanceResources();
this.markdownContainer.clear();
if (this.fallbackToPlainMarkdownValue) {
this.markdownContainer.clear();
const element = this.fallbackElement.nativeElement;
element.innerHTML = template;
this.handlePlugins(element);

View File

@ -137,7 +137,6 @@ export interface TenantProfile extends BaseData<TenantProfileId> {
name: string;
description?: string;
default?: boolean;
isolatedTbCore?: boolean;
isolatedTbRuleEngine?: boolean;
profileData?: TenantProfileData;
}

View File

@ -2550,9 +2550,7 @@
"tenant-required": "Tenant je povinný",
"search": "Vyhledat tenanty",
"selected-tenants": "Vybráno { count, plural, 1 {1 tenantů} other {# tenantů} }",
"isolated-tb-core": "Zpracování v izolovaném kontejneru ThingsBoard Core",
"isolated-tb-rule-engine": "Zpracování v izolovaném kontejneru ThingsBoard Rule Engine",
"isolated-tb-core-details": "Vyžaduje samostatnou mikroslužbu(y) pro každého izolovaného tenanta",
"isolated-tb-rule-engine-details": "Vyžaduje samostatnou mikroslužbu(y) pro každého izolovaného tenanta"
},
"tenant-profile": {

View File

@ -3053,9 +3053,7 @@
"tenant-required": "Tenant is required",
"search": "Search tenants",
"selected-tenants": "{ count, plural, 1 {1 tenant} other {# tenants} } selected",
"isolated-tb-core": "Processing in isolated ThingsBoard Core container",
"isolated-tb-rule-engine": "Processing in isolated ThingsBoard Rule Engine container",
"isolated-tb-core-details": "Requires separate microservice(s) per isolated Tenant",
"isolated-tb-rule-engine-details": "Requires separate microservice(s) per isolated Tenant"
},
"tenant-profile": {

View File

@ -3029,9 +3029,7 @@
"tenant-required": "Propietario requerido",
"search": "Buscar propietarios",
"selected-tenants": "{ count, plural, 1 {1 propietario} other {# propietarios} } seleccionados",
"isolated-tb-core": "Procesando en contenedor aislado",
"isolated-tb-rule-engine": "Procesando en contenedor Motor de Reglas aislado",
"isolated-tb-core-details": "Requiere microservicios separados por propietario aislado",
"isolated-tb-rule-engine-details": "Requiere microservicios separados por propietario aislado"
},
"tenant-profile": {

View File

@ -1997,9 +1997,7 @@
"tenant-required": "테넌트가 필요합니다.",
"search": "테넌트 검색",
"selected-tenants": "{ count, plural, 1 {1 개 테넌트} other {# 개 테넌트} } 선택됨",
"isolated-tb-core": "Processing in isolated ThingsBoard Core container",
"isolated-tb-rule-engine": "Processing in isolated ThingsBoard Rule Engine container",
"isolated-tb-core-details": "Requires separate microservice(s) per isolated Tenant",
"isolated-tb-rule-engine-details": "Requires separate microservice(s) per isolated Tenant"
},
"tenant-profile": {

View File

@ -1659,9 +1659,7 @@
"tenant-required": "O locatário é obrigatório",
"search": "Pesquisar locatários",
"selected-tenants": "{ count, plural, 1 {1 tenant} other {# tenants} } selecionado(s)",
"isolated-tb-core": "Processamento em contêiner isolado do ThingsBoard Core",
"isolated-tb-rule-engine": "Processamento em contêiner isolado do ThingsBoard Rule Engine",
"isolated-tb-core-details": "Exige microsserviço(s) separado(s) para cada locatário isolado",
"isolated-tb-rule-engine-details": "Exige microsserviço(s) separado(s) para cada locatário isolado"
},
"timeinterval": {

View File

@ -1997,9 +1997,7 @@
"tenant-required": "Najemnik je obvezen",
"search": "Iskanje najemnikov",
"selected-tenants": "{ count, plural, 1 {1 tenant} other {# tenants} } izbran",
"isolated-tb-core": "Obdelava v izoliranem odlagališču ThingsBoard Core",
"isolated-tb-rule-engine": "Obdelava v izoliranem odlagališču ThingsBoard Rule Engine",
"isolated-tb-core-details": "Zahteva ločene mikro storitve na izoliranega najemnika",
"isolated-tb-rule-engine-details": "Zahteva ločene mikro storitve na izoliranega najemnika"
},
"tenant-profile": {

View File

@ -2569,9 +2569,7 @@
"tenant-required": "Tenant gerekli",
"search": "Tenantları ara",
"selected-tenants": "{ count, plural, 1 {1 tenant} other {# tenant} } seçildi",
"isolated-tb-core": "ThingsBoard soyutlanmış merkezi konteynerda işlensin",
"isolated-tb-rule-engine": "ThingsBoard soyutlanmış kural yönetimi konteynerda işlensin",
"isolated-tb-core-details": "Her soyutlanmış tenant ayrı bir mikro servis gerektirir",
"isolated-tb-rule-engine-details": "Her soyutlanmış tenant ayrı bir mikro servis gerektirir"
},
"tenant-profile": {

View File

@ -2476,8 +2476,6 @@
"details": "详情",
"events": "事件",
"idCopiedMessage": "租户ID已经复制到粘贴板",
"isolated-tb-core": "隔离板芯容器中的加工",
"isolated-tb-core-details": "每个独立租户需要单独的微服务",
"isolated-tb-rule-engine": "在独立的ThingsBoard规则引擎容器中处理",
"isolated-tb-rule-engine-details": "每个独立租户需要单独的微服务",
"manage-tenant-admins": "管理租户管理员",