Ordering and localization

This commit is contained in:
Andrii Shvaika 2022-06-01 13:56:35 +03:00
parent 654305198d
commit 5a0eb8b640
20 changed files with 87 additions and 19 deletions

View File

@ -141,6 +141,7 @@ import org.thingsboard.server.service.security.permission.AccessControlService;
import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.permission.Resource;
import org.thingsboard.server.service.state.DeviceStateService; import org.thingsboard.server.service.state.DeviceStateService;
import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService;
import org.thingsboard.server.service.telemetry.AlarmSubscriptionService; import org.thingsboard.server.service.telemetry.AlarmSubscriptionService;
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
@ -283,6 +284,9 @@ public abstract class BaseController {
@Autowired @Autowired
protected QueueService queueService; protected QueueService queueService;
@Autowired
protected EntitiesVersionControlService vcService;
@Value("${server.log_controller_error_stack_trace}") @Value("${server.log_controller_error_stack_trace}")
@Getter @Getter
private boolean logControllerErrorStackTrace; private boolean logControllerErrorStackTrace;

View File

@ -220,6 +220,7 @@ public class DeviceProfileController extends BaseController {
} }
} }
DeviceProfile savedDeviceProfile = checkNotNull(deviceProfileService.saveDeviceProfile(deviceProfile)); DeviceProfile savedDeviceProfile = checkNotNull(deviceProfileService.saveDeviceProfile(deviceProfile));
vcService.autoCommit(getCurrentUser(), savedDeviceProfile.getId());
tbClusterService.onDeviceProfileChange(savedDeviceProfile, null); tbClusterService.onDeviceProfileChange(savedDeviceProfile, null);
tbClusterService.broadcastEntityStateChangeEvent(deviceProfile.getTenantId(), savedDeviceProfile.getId(), tbClusterService.broadcastEntityStateChangeEvent(deviceProfile.getTenantId(), savedDeviceProfile.getId(),

View File

@ -83,6 +83,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -253,6 +254,7 @@ public class RuleChainController extends BaseController {
checkEntity(ruleChain.getId(), ruleChain, Resource.RULE_CHAIN); checkEntity(ruleChain.getId(), ruleChain, Resource.RULE_CHAIN);
RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain)); RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain));
vcService.autoCommit(getCurrentUser(), savedRuleChain.getId());
if (RuleChainType.CORE.equals(savedRuleChain.getType())) { if (RuleChainType.CORE.equals(savedRuleChain.getType())) {
tbClusterService.broadcastEntityStateChangeEvent(ruleChain.getTenantId(), savedRuleChain.getId(), tbClusterService.broadcastEntityStateChangeEvent(ruleChain.getTenantId(), savedRuleChain.getId(),
@ -293,6 +295,7 @@ public class RuleChainController extends BaseController {
checkParameter(request.getName(), "name"); checkParameter(request.getName(), "name");
RuleChain savedRuleChain = installScripts.createDefaultRuleChain(getCurrentUser().getTenantId(), request.getName()); RuleChain savedRuleChain = installScripts.createDefaultRuleChain(getCurrentUser().getTenantId(), request.getName());
vcService.autoCommit(getCurrentUser(), savedRuleChain.getId());
tbClusterService.broadcastEntityStateChangeEvent(savedRuleChain.getTenantId(), savedRuleChain.getId(), ComponentLifecycleEvent.CREATED); tbClusterService.broadcastEntityStateChangeEvent(savedRuleChain.getTenantId(), savedRuleChain.getId(), ComponentLifecycleEvent.CREATED);
@ -382,6 +385,15 @@ public class RuleChainController extends BaseController {
updatedRuleChains = Collections.emptyList(); updatedRuleChains = Collections.emptyList();
} }
if (updatedRuleChains.isEmpty()) {
vcService.autoCommit(getCurrentUser(), ruleChainMetaData.getRuleChainId());
} else {
List<UUID> uuids = new ArrayList<>(updatedRuleChains.size() + 1);
uuids.add(ruleChainMetaData.getRuleChainId().getId());
updatedRuleChains.forEach(rc -> uuids.add(rc.getId().getId()));
vcService.autoCommit(getCurrentUser(), EntityType.RULE_CHAIN, uuids);
}
RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId())); RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId()));
if (RuleChainType.CORE.equals(ruleChain.getType())) { if (RuleChainType.CORE.equals(ruleChain.getType())) {

View File

@ -46,6 +46,7 @@ public class DefaultTbAssetService extends AbstractTbEntityService implements Tb
TenantId tenantId = asset.getTenantId(); TenantId tenantId = asset.getTenantId();
try { try {
Asset savedAsset = checkNotNull(assetService.saveAsset(asset)); Asset savedAsset = checkNotNull(assetService.saveAsset(asset));
vcService.autoCommit(user, savedAsset.getId());
notificationEntityService.notifyCreateOrUpdateEntity(tenantId, savedAsset.getId(), asset, savedAsset.getCustomerId(), actionType, user); notificationEntityService.notifyCreateOrUpdateEntity(tenantId, savedAsset.getId(), asset, savedAsset.getCustomerId(), actionType, user);
return savedAsset; return savedAsset;
} catch (Exception e) { } catch (Exception e) {

View File

@ -45,6 +45,7 @@ public class DefaultTbCustomerService extends AbstractTbEntityService implements
TenantId tenantId = customer.getTenantId(); TenantId tenantId = customer.getTenantId();
try { try {
Customer savedCustomer = checkNotNull(customerService.saveCustomer(customer)); Customer savedCustomer = checkNotNull(customerService.saveCustomer(customer));
vcService.autoCommit(user, savedCustomer.getId());
notificationEntityService.notifyCreateOrUpdateEntity(tenantId, savedCustomer.getId(), savedCustomer, savedCustomer.getId(), actionType, user); notificationEntityService.notifyCreateOrUpdateEntity(tenantId, savedCustomer.getId(), savedCustomer, savedCustomer.getId(), actionType, user);
return savedCustomer; return savedCustomer;
} catch (Exception e) { } catch (Exception e) {

View File

@ -54,6 +54,7 @@ public class DefaultTbDeviceService extends AbstractTbEntityService implements T
ActionType actionType = device.getId() == null ? ActionType.ADDED : ActionType.UPDATED; ActionType actionType = device.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
try { try {
Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken)); Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken));
vcService.autoCommit(user, savedDevice.getId());
notificationEntityService.notifyCreateOrUpdateDevice(tenantId, savedDevice.getId(), savedDevice.getCustomerId(), notificationEntityService.notifyCreateOrUpdateDevice(tenantId, savedDevice.getId(), savedDevice.getCustomerId(),
savedDevice, oldDevice, actionType, user); savedDevice, oldDevice, actionType, user);

View File

@ -40,6 +40,7 @@ import org.thingsboard.server.service.sync.ie.exporting.ExportableEntitiesServic
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -111,7 +112,7 @@ public class DefaultEntityExportService<I extends EntityId, E extends Exportable
} else { } else {
scopes = Collections.singletonList(DataConstants.SERVER_SCOPE); scopes = Collections.singletonList(DataConstants.SERVER_SCOPE);
} }
Map<String, List<AttributeExportData>> attributes = new HashMap<>(); Map<String, List<AttributeExportData>> attributes = new LinkedHashMap<>();
scopes.forEach(scope -> { scopes.forEach(scope -> {
try { try {
attributes.put(scope, attributesService.findAll(user.getTenantId(), entity.getId(), scope).get().stream() attributes.put(scope, attributesService.findAll(user.getTenantId(), entity.getId(), scope).get().stream()

View File

@ -53,6 +53,7 @@ import org.thingsboard.server.common.data.sync.vc.VersionLoadResult;
import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo; import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo;
import org.thingsboard.server.common.data.sync.vc.request.create.AutoVersionCreateConfig; import org.thingsboard.server.common.data.sync.vc.request.create.AutoVersionCreateConfig;
import org.thingsboard.server.common.data.sync.vc.request.create.ComplexVersionCreateRequest; import org.thingsboard.server.common.data.sync.vc.request.create.ComplexVersionCreateRequest;
import org.thingsboard.server.common.data.sync.vc.request.create.EntityTypeVersionCreateConfig;
import org.thingsboard.server.common.data.sync.vc.request.create.SingleEntityVersionCreateRequest; import org.thingsboard.server.common.data.sync.vc.request.create.SingleEntityVersionCreateRequest;
import org.thingsboard.server.common.data.sync.vc.request.create.SyncStrategy; import org.thingsboard.server.common.data.sync.vc.request.create.SyncStrategy;
import org.thingsboard.server.common.data.sync.vc.request.create.VersionCreateConfig; import org.thingsboard.server.common.data.sync.vc.request.create.VersionCreateConfig;
@ -77,6 +78,7 @@ import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -418,6 +420,35 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
return saveEntitiesVersion(user, vcr); return saveEntitiesVersion(user, vcr);
} }
@Override
public ListenableFuture<VersionCreationResult> autoCommit(SecurityUser user, EntityType entityType, List<UUID> entityIds) throws Exception {
var repositorySettings = repositorySettingsService.get(user.getTenantId());
if (repositorySettings == null) {
return Futures.immediateFuture(null);
}
var autoCommitSettings = autoCommitSettingsService.get(user.getTenantId());
if (autoCommitSettings == null) {
return Futures.immediateFuture(null);
}
AutoVersionCreateConfig autoCommitConfig = autoCommitSettings.get(entityType);
if (autoCommitConfig == null) {
return Futures.immediateFuture(null);
}
var autoCommitBranchName = autoCommitConfig.getBranch();
if (StringUtils.isEmpty(autoCommitBranchName)) {
autoCommitBranchName = StringUtils.isNotEmpty(repositorySettings.getDefaultBranch()) ? repositorySettings.getDefaultBranch() : "auto-commits";
}
ComplexVersionCreateRequest vcr = new ComplexVersionCreateRequest();
vcr.setBranch(autoCommitBranchName);
vcr.setVersionName("auto-commit at " + Instant.ofEpochSecond(System.currentTimeMillis() / 1000));
vcr.setSyncStrategy(SyncStrategy.MERGE);
EntityTypeVersionCreateConfig vcrConfig = new EntityTypeVersionCreateConfig();
vcrConfig.setEntityIds(entityIds);
vcr.setEntityTypes(Collections.singletonMap(entityType, vcrConfig));
return saveEntitiesVersion(user, vcr);
}
private String getCauseMessage(Exception e) { private String getCauseMessage(Exception e) {
String message; String message;
if (e.getCause() != null && StringUtils.isNotEmpty(e.getCause().getMessage())) { if (e.getCause() != null && StringUtils.isNotEmpty(e.getCause().getMessage())) {

View File

@ -108,7 +108,7 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
public ListenableFuture<Void> addToCommit(CommitGitRequest commit, EntityExportData<ExportableEntity<EntityId>> entityData) { public ListenableFuture<Void> addToCommit(CommitGitRequest commit, EntityExportData<ExportableEntity<EntityId>> entityData) {
SettableFuture<Void> future = SettableFuture.create(); SettableFuture<Void> future = SettableFuture.create();
String path = getRelativePath(entityData.getEntityType(), entityData.getEntity().getId()); String path = getRelativePath(entityData.getEntityType(), getExternalId(entityData.getEntity()));
String entityDataJson = JacksonUtil.toPrettyString(entityData.sort()); String entityDataJson = JacksonUtil.toPrettyString(entityData.sort());
registerAndSend(commit, builder -> builder.setCommitRequest( registerAndSend(commit, builder -> builder.setCommitRequest(
@ -120,6 +120,10 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
return future; return future;
} }
private EntityId getExternalId(ExportableEntity<EntityId> entity) {
return entity.getExternalId() != null ? entity.getExternalId() : entity.getId();
}
@Override @Override
public ListenableFuture<Void> deleteAll(CommitGitRequest commit, EntityType entityType) { public ListenableFuture<Void> deleteAll(CommitGitRequest commit, EntityType entityType) {
SettableFuture<Void> future = SettableFuture.create(); SettableFuture<Void> future = SettableFuture.create();

View File

@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.sync.vc.request.load.VersionLoadReques
import org.thingsboard.server.common.data.sync.vc.request.create.VersionCreateRequest; import org.thingsboard.server.common.data.sync.vc.request.create.VersionCreateRequest;
import java.util.List; import java.util.List;
import java.util.UUID;
public interface EntitiesVersionControlService { public interface EntitiesVersionControlService {
@ -64,5 +65,7 @@ public interface EntitiesVersionControlService {
ListenableFuture<VersionCreationResult> autoCommit(SecurityUser user, EntityId entityId) throws Exception; ListenableFuture<VersionCreationResult> autoCommit(SecurityUser user, EntityId entityId) throws Exception;
ListenableFuture<VersionCreationResult> autoCommit(SecurityUser user, EntityType entityType, List<UUID> entityIds) throws Exception;
ListenableFuture<EntityDataInfo> getEntityDataInfo(SecurityUser user, EntityId entityId, String versionId); ListenableFuture<EntityDataInfo> getEntityDataInfo(SecurityUser user, EntityId entityId, String versionId);
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.server.common.data.sync.ie; package org.thingsboard.server.common.data.sync.ie;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
@ -26,6 +27,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials;
@Data @Data
public class DeviceExportData extends EntityExportData<Device> { public class DeviceExportData extends EntityExportData<Device> {
@JsonProperty(index = 3)
private DeviceCredentials credentials; private DeviceCredentials credentials;
} }

View File

@ -17,6 +17,8 @@ package org.thingsboard.server.common.data.sync.ie;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
@ -52,11 +54,15 @@ public class EntityExportData<E extends ExportableEntity<? extends EntityId>> {
public static final Comparator<AttributeExportData> attrComparator = Comparator public static final Comparator<AttributeExportData> attrComparator = Comparator
.comparing(AttributeExportData::getKey).thenComparing(AttributeExportData::getLastUpdateTs); .comparing(AttributeExportData::getKey).thenComparing(AttributeExportData::getLastUpdateTs);
@JsonProperty(index = 2)
@JsonTbEntity @JsonTbEntity
private E entity; private E entity;
@JsonProperty(index = 1)
private EntityType entityType; private EntityType entityType;
@JsonProperty(index = 100)
private List<EntityRelation> relations; private List<EntityRelation> relations;
@JsonProperty(index = 101)
private Map<String, List<AttributeExportData>> attributes; private Map<String, List<AttributeExportData>> attributes;
public EntityExportData<E> sort() { public EntityExportData<E> sort() {

View File

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.server.common.data.sync.ie; package org.thingsboard.server.common.data.sync.ie;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
@ -26,6 +27,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData;
@Data @Data
public class RuleChainExportData extends EntityExportData<RuleChain> { public class RuleChainExportData extends EntityExportData<RuleChain> {
@JsonProperty(index = 3)
private RuleChainMetaData metaData; private RuleChainMetaData metaData;
} }

View File

@ -33,7 +33,8 @@ import java.util.Arrays;
public class JacksonUtil { public class JacksonUtil {
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
public static final ObjectMapper PRETTY_SORTED_JSON_MAPPER = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT) public static final ObjectMapper PRETTY_SORTED_JSON_MAPPER = JsonMapper.builder()
.enable(SerializationFeature.INDENT_OUTPUT)
.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true) .configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true)
.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true) .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
.build(); .build();

View File

@ -76,10 +76,10 @@
</div> </div>
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px" formGroupName="config"> <div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px" formGroupName="config">
<mat-checkbox formControlName="saveRelations"> <mat-checkbox formControlName="saveRelations">
{{ 'version-control.export-entity-relations' | translate }} {{ 'version-control.export-relations' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox formControlName="saveAttributes"> <mat-checkbox formControlName="saveAttributes">
{{ 'version-control.export-entity-attributes' | translate }} {{ 'version-control.export-attributes' | translate }}
</mat-checkbox> </mat-checkbox>
</div> </div>
</div> </div>

View File

@ -66,10 +66,10 @@
</mat-form-field> </mat-form-field>
<div fxFlex fxLayout="column" fxLayoutGap="8px"> <div fxFlex fxLayout="column" fxLayoutGap="8px">
<mat-checkbox formControlName="saveRelations"> <mat-checkbox formControlName="saveRelations">
{{ 'version-control.export-entity-relations' | translate }} {{ 'version-control.export-relations' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox formControlName="saveAttributes"> <mat-checkbox formControlName="saveAttributes">
{{ 'version-control.export-entity-attributes' | translate }} {{ 'version-control.export-attributes' | translate }}
</mat-checkbox> </mat-checkbox>
</div> </div>
</div> </div>

View File

@ -65,10 +65,10 @@
</div> </div>
<div fxFlex fxLayout="column" fxLayoutGap="8px"> <div fxFlex fxLayout="column" fxLayoutGap="8px">
<mat-checkbox formControlName="loadRelations"> <mat-checkbox formControlName="loadRelations">
{{ 'version-control.load-entities-relations' | translate }} {{ 'version-control.load-relations' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox formControlName="loadAttributes"> <mat-checkbox formControlName="loadAttributes">
{{ 'version-control.load-entities-attributes' | translate }} {{ 'version-control.load-attributes' | translate }}
</mat-checkbox> </mat-checkbox>
</div> </div>
</div> </div>

View File

@ -39,10 +39,10 @@
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-checkbox formControlName="saveRelations" style="margin-bottom: 16px;"> <mat-checkbox formControlName="saveRelations" style="margin-bottom: 16px;">
{{ 'version-control.export-entity-relations' | translate }} {{ 'version-control.export-relations' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox formControlName="saveAttributes" style="margin-bottom: 16px;"> <mat-checkbox formControlName="saveAttributes" style="margin-bottom: 16px;">
{{ 'version-control.export-entity-attributes' | translate }} {{ 'version-control.export-attributes' | translate }}
</mat-checkbox> </mat-checkbox>
</div> </div>
</fieldset> </fieldset>

View File

@ -27,10 +27,10 @@
<fieldset [disabled]="isLoading$ | async"> <fieldset [disabled]="isLoading$ | async">
<div fxFlex fxLayout="column"> <div fxFlex fxLayout="column">
<mat-checkbox formControlName="loadRelations" style="margin-bottom: 16px;"> <mat-checkbox formControlName="loadRelations" style="margin-bottom: 16px;">
{{ 'version-control.load-entity-relations' | translate }} {{ 'version-control.load-relations' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox formControlName="loadAttributes" style="margin-bottom: 16px;"> <mat-checkbox formControlName="loadAttributes" style="margin-bottom: 16px;">
{{ 'version-control.load-entity-attributes' | translate }} {{ 'version-control.load-attributes' | translate }}
</mat-checkbox> </mat-checkbox>
</div> </div>
</fieldset> </fieldset>

View File

@ -3125,8 +3125,8 @@
"version-name": "Version name", "version-name": "Version name",
"version-name-required": "Version name is required", "version-name-required": "Version name is required",
"author": "Author", "author": "Author",
"export-entity-relations": "Export entity relations", "export-relations": "Export relations",
"export-entity-attributes": "Export entity attributes", "export-attributes": "Export attributes",
"entity-versions": "Entity versions", "entity-versions": "Entity versions",
"versions": "Versions", "versions": "Versions",
"created-time": "Created time", "created-time": "Created time",
@ -3138,8 +3138,8 @@
"nothing-to-commit": "No changes to commit", "nothing-to-commit": "No changes to commit",
"restore-version": "Restore version", "restore-version": "Restore version",
"restore-entity-from-version": "Restore entity from version '{{versionName}}'", "restore-entity-from-version": "Restore entity from version '{{versionName}}'",
"load-entity-relations": "Load entity relations", "load-relations": "Load relations",
"load-entity-attributes": "Load entity attributes", "load-attributes": "Load attributes",
"show-version-diff": "Show version diff", "show-version-diff": "Show version diff",
"diff-entity-with-version": "Diff with entity version '{{versionName}}'", "diff-entity-with-version": "Diff with entity version '{{versionName}}'",
"previous-difference": "Previous Difference", "previous-difference": "Previous Difference",
@ -3159,8 +3159,6 @@
"add-entity-type": "Add entity type", "add-entity-type": "Add entity type",
"remove-all": "Remove all", "remove-all": "Remove all",
"version-create-result": "{ added, plural, 0 {No entities} 1 {1 entity} other {# entities} } added.\n{ modified, plural, 0 {No entities} 1 {1 entity} other {# entities} } modified.\n{ removed, plural, 0 {No entities} 1 {1 entity} other {# entities} } removed.", "version-create-result": "{ added, plural, 0 {No entities} 1 {1 entity} other {# entities} } added.\n{ modified, plural, 0 {No entities} 1 {1 entity} other {# entities} } modified.\n{ removed, plural, 0 {No entities} 1 {1 entity} other {# entities} } removed.",
"load-entities-relations": "Load entities relations",
"load-entities-attributes": "Load entities attributes",
"remove-other-entities": "Remove other entities", "remove-other-entities": "Remove other entities",
"find-existing-entity-by-name": "Find existing entity by name", "find-existing-entity-by-name": "Find existing entity by name",
"restore-entities-from-version": "Restore entities from version '{{versionName}}'", "restore-entities-from-version": "Restore entities from version '{{versionName}}'",