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.Resource;
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.TelemetrySubscriptionService;
@ -283,6 +284,9 @@ public abstract class BaseController {
@Autowired
protected QueueService queueService;
@Autowired
protected EntitiesVersionControlService vcService;
@Value("${server.log_controller_error_stack_trace}")
@Getter
private boolean logControllerErrorStackTrace;

View File

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

View File

@ -83,6 +83,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@ -253,6 +254,7 @@ public class RuleChainController extends BaseController {
checkEntity(ruleChain.getId(), ruleChain, Resource.RULE_CHAIN);
RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain));
vcService.autoCommit(getCurrentUser(), savedRuleChain.getId());
if (RuleChainType.CORE.equals(savedRuleChain.getType())) {
tbClusterService.broadcastEntityStateChangeEvent(ruleChain.getTenantId(), savedRuleChain.getId(),
@ -293,6 +295,7 @@ public class RuleChainController extends BaseController {
checkParameter(request.getName(), "name");
RuleChain savedRuleChain = installScripts.createDefaultRuleChain(getCurrentUser().getTenantId(), request.getName());
vcService.autoCommit(getCurrentUser(), savedRuleChain.getId());
tbClusterService.broadcastEntityStateChangeEvent(savedRuleChain.getTenantId(), savedRuleChain.getId(), ComponentLifecycleEvent.CREATED);
@ -382,6 +385,15 @@ public class RuleChainController extends BaseController {
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()));
if (RuleChainType.CORE.equals(ruleChain.getType())) {

View File

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

View File

@ -45,6 +45,7 @@ public class DefaultTbCustomerService extends AbstractTbEntityService implements
TenantId tenantId = customer.getTenantId();
try {
Customer savedCustomer = checkNotNull(customerService.saveCustomer(customer));
vcService.autoCommit(user, savedCustomer.getId());
notificationEntityService.notifyCreateOrUpdateEntity(tenantId, savedCustomer.getId(), savedCustomer, savedCustomer.getId(), actionType, user);
return savedCustomer;
} 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;
try {
Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken));
vcService.autoCommit(user, savedDevice.getId());
notificationEntityService.notifyCreateOrUpdateDevice(tenantId, savedDevice.getId(), savedDevice.getCustomerId(),
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.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@ -111,7 +112,7 @@ public class DefaultEntityExportService<I extends EntityId, E extends Exportable
} else {
scopes = Collections.singletonList(DataConstants.SERVER_SCOPE);
}
Map<String, List<AttributeExportData>> attributes = new HashMap<>();
Map<String, List<AttributeExportData>> attributes = new LinkedHashMap<>();
scopes.forEach(scope -> {
try {
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.request.create.AutoVersionCreateConfig;
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.SyncStrategy;
import org.thingsboard.server.common.data.sync.vc.request.create.VersionCreateConfig;
@ -77,6 +78,7 @@ import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -418,6 +420,35 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
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) {
String message;
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) {
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());
registerAndSend(commit, builder -> builder.setCommitRequest(
@ -120,6 +120,10 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
return future;
}
private EntityId getExternalId(ExportableEntity<EntityId> entity) {
return entity.getExternalId() != null ? entity.getExternalId() : entity.getId();
}
@Override
public ListenableFuture<Void> deleteAll(CommitGitRequest commit, EntityType entityType) {
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 java.util.List;
import java.util.UUID;
public interface EntitiesVersionControlService {
@ -64,5 +65,7 @@ public interface EntitiesVersionControlService {
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);
}

View File

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.common.data.sync.ie;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ -26,6 +27,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials;
@Data
public class DeviceExportData extends EntityExportData<Device> {
@JsonProperty(index = 3)
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.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.Type;
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
.comparing(AttributeExportData::getKey).thenComparing(AttributeExportData::getLastUpdateTs);
@JsonProperty(index = 2)
@JsonTbEntity
private E entity;
@JsonProperty(index = 1)
private EntityType entityType;
@JsonProperty(index = 100)
private List<EntityRelation> relations;
@JsonProperty(index = 101)
private Map<String, List<AttributeExportData>> attributes;
public EntityExportData<E> sort() {

View File

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

View File

@ -33,7 +33,8 @@ import java.util.Arrays;
public class JacksonUtil {
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(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
.build();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3125,8 +3125,8 @@
"version-name": "Version name",
"version-name-required": "Version name is required",
"author": "Author",
"export-entity-relations": "Export entity relations",
"export-entity-attributes": "Export entity attributes",
"export-relations": "Export relations",
"export-attributes": "Export attributes",
"entity-versions": "Entity versions",
"versions": "Versions",
"created-time": "Created time",
@ -3138,8 +3138,8 @@
"nothing-to-commit": "No changes to commit",
"restore-version": "Restore version",
"restore-entity-from-version": "Restore entity from version '{{versionName}}'",
"load-entity-relations": "Load entity relations",
"load-entity-attributes": "Load entity attributes",
"load-relations": "Load relations",
"load-attributes": "Load attributes",
"show-version-diff": "Show version diff",
"diff-entity-with-version": "Diff with entity version '{{versionName}}'",
"previous-difference": "Previous Difference",
@ -3159,8 +3159,6 @@
"add-entity-type": "Add entity type",
"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.",
"load-entities-relations": "Load entities relations",
"load-entities-attributes": "Load entities attributes",
"remove-other-entities": "Remove other entities",
"find-existing-entity-by-name": "Find existing entity by name",
"restore-entities-from-version": "Restore entities from version '{{versionName}}'",