Dashboard/widget resources export - process whole config
This commit is contained in:
parent
a411213d6c
commit
8ba34a953a
@ -17,6 +17,7 @@ package org.thingsboard.server.controller;
|
||||
|
||||
import com.datastax.oss.driver.api.core.uuid.Uuids;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@ -602,13 +603,14 @@ public class DashboardControllerTest extends AbstractControllerTest {
|
||||
dashboard.setTitle("My dashboard");
|
||||
dashboard.setConfiguration(JacksonUtil.newObjectNode()
|
||||
.put("someImage", "tb-image;/api/images/tenant/" + imageInfo.getResourceKey())
|
||||
.set("widgets", JacksonUtil.toJsonNode("""
|
||||
.<ObjectNode>set("widgets", JacksonUtil.toJsonNode("""
|
||||
{"xxx":
|
||||
{"config":{"actions":{"elementClick":[
|
||||
{"customResources":[{"url":{"entityType":"TB_RESOURCE","id":
|
||||
"tb-resource;/api/resource/js_module/tenant/gateway-management-extension.js"},"isModule":true},
|
||||
{"url":"tb-resource;/api/resource/js_module/tenant/gateway-management-extension.js","isModule":true}]}]}}}}
|
||||
""")));
|
||||
"""))
|
||||
.put("someResource", "tb-resource;/api/resource/js_module/tenant/gateway-management-extension.js"));
|
||||
dashboard = doPost("/api/dashboard", dashboard, Dashboard.class);
|
||||
|
||||
Dashboard exportedDashboard = doGet("/api/dashboard/" + dashboard.getUuidId() + "?includeResources=true", Dashboard.class);
|
||||
@ -637,12 +639,18 @@ public class DashboardControllerTest extends AbstractControllerTest {
|
||||
doPost("/api/resource", resource, TbResourceInfo.class);
|
||||
|
||||
Dashboard importedDashboard = doPost("/api/dashboard", exportedDashboard, Dashboard.class);
|
||||
String newResourceKey = "gateway-management-extension_(1).js";
|
||||
|
||||
imageRef = importedDashboard.getConfiguration().get("someImage").asText();
|
||||
assertThat(imageRef).isEqualTo("tb-image;/api/images/tenant/" + imageInfo.getResourceKey());
|
||||
resourceRef = importedDashboard.getConfiguration().get("widgets").get("xxx").get("config")
|
||||
.get("actions").get("elementClick").get(0).get("customResources").get(0).get("url").asText();
|
||||
String newResourceKey = "gateway-management-extension_(1).js";
|
||||
assertThat(resourceRef).isEqualTo("tb-resource;/api/resource/js_module/tenant/" + newResourceKey);
|
||||
|
||||
List<String> resourcesRefs = new ArrayList<>();
|
||||
resourcesRefs.add(importedDashboard.getConfiguration().get("widgets").get("xxx").get("config")
|
||||
.get("actions").get("elementClick").get(0).get("customResources").get(0).get("url").asText());
|
||||
resourcesRefs.add(importedDashboard.getConfiguration().get("someResource").asText());
|
||||
assertThat(resourcesRefs).allSatisfy(ref -> {
|
||||
assertThat(ref).isEqualTo("tb-resource;/api/resource/js_module/tenant/" + newResourceKey);
|
||||
});
|
||||
|
||||
TbResourceInfo importedImageInfo = doGet("/api/images/tenant/" + imageInfo.getResourceKey() + "/info", TbResourceInfo.class);
|
||||
assertThat(importedImageInfo.getEtag()).isEqualTo(imageInfo.getEtag());
|
||||
|
||||
@ -57,6 +57,7 @@ import org.thingsboard.server.dao.service.Validator;
|
||||
import org.thingsboard.server.dao.service.validator.ResourceDataValidator;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@ -403,16 +404,26 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
|
||||
@Override
|
||||
public boolean updateResourcesUsage(Dashboard dashboard) {
|
||||
Map<String, String> links = getResourcesLinks(dashboard.getResources());
|
||||
return updateResourcesUsage(dashboard.getTenantId(), dashboard.getConfiguration(), DASHBOARD_RESOURCES_MAPPING, links);
|
||||
return updateResourcesUsage(dashboard.getTenantId(), List.of(dashboard.getConfiguration()), List.of(DASHBOARD_RESOURCES_MAPPING), links);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateResourcesUsage(WidgetTypeDetails widgetTypeDetails) {
|
||||
Map<String, String> links = getResourcesLinks(widgetTypeDetails.getResources());
|
||||
boolean updated = updateResourcesUsage(widgetTypeDetails.getTenantId(), widgetTypeDetails.getDescriptor(), WIDGET_RESOURCES_MAPPING, links);
|
||||
List<JsonNode> jsonNodes = new ArrayList<>(2);
|
||||
List<Map<String, String>> mappings = new ArrayList<>(2);
|
||||
|
||||
jsonNodes.add(widgetTypeDetails.getDescriptor());
|
||||
mappings.add(WIDGET_RESOURCES_MAPPING);
|
||||
|
||||
JsonNode defaultConfig = widgetTypeDetails.getDefaultConfig();
|
||||
if (defaultConfig != null) {
|
||||
updated |= updateResourcesUsage(widgetTypeDetails.getTenantId(), defaultConfig, WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING, links);
|
||||
jsonNodes.add(defaultConfig);
|
||||
mappings.add(WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING);
|
||||
}
|
||||
|
||||
boolean updated = updateResourcesUsage(widgetTypeDetails.getTenantId(), jsonNodes, mappings, links);
|
||||
if (defaultConfig != null) {
|
||||
widgetTypeDetails.setDefaultConfig(defaultConfig);
|
||||
}
|
||||
return updated;
|
||||
@ -433,8 +444,9 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
|
||||
return links;
|
||||
}
|
||||
|
||||
private boolean updateResourcesUsage(TenantId tenantId, JsonNode jsonNode, Map<String, String> mapping, Map<String, String> links) {
|
||||
return processResources(jsonNode, mapping, value -> {
|
||||
private boolean updateResourcesUsage(TenantId tenantId, List<JsonNode> jsonNodes, List<Map<String, String>> mappings, Map<String, String> links) {
|
||||
log.trace("[{}] updateResourcesUsage (new links: {}) for {}", tenantId, links, jsonNodes);
|
||||
return processResources(jsonNodes, mappings, value -> {
|
||||
String link = getResourceLink(value);
|
||||
if (link != null) {
|
||||
String newLink = links.get(link);
|
||||
@ -463,22 +475,30 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
|
||||
|
||||
@Override
|
||||
public Collection<TbResourceInfo> getUsedResources(Dashboard dashboard) {
|
||||
return getUsedResources(dashboard.getTenantId(), dashboard.getConfiguration(), DASHBOARD_RESOURCES_MAPPING).values();
|
||||
return getUsedResources(dashboard.getTenantId(), List.of(dashboard.getConfiguration()), List.of(DASHBOARD_RESOURCES_MAPPING)).values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<TbResourceInfo> getUsedResources(WidgetTypeDetails widgetTypeDetails) {
|
||||
Map<TbResourceId, TbResourceInfo> resources = getUsedResources(widgetTypeDetails.getTenantId(), widgetTypeDetails.getDescriptor(), WIDGET_RESOURCES_MAPPING);
|
||||
List<JsonNode> jsonNodes = new ArrayList<>(2);
|
||||
List<Map<String, String>> mappings = new ArrayList<>(2);
|
||||
|
||||
jsonNodes.add(widgetTypeDetails.getDescriptor());
|
||||
mappings.add(WIDGET_RESOURCES_MAPPING);
|
||||
|
||||
JsonNode defaultConfig = widgetTypeDetails.getDefaultConfig();
|
||||
if (defaultConfig != null) {
|
||||
resources.putAll(getUsedResources(widgetTypeDetails.getTenantId(), defaultConfig, WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING));
|
||||
jsonNodes.add(defaultConfig);
|
||||
mappings.add(WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING);
|
||||
}
|
||||
return resources.values();
|
||||
|
||||
return getUsedResources(widgetTypeDetails.getTenantId(), jsonNodes, mappings).values();
|
||||
}
|
||||
|
||||
private Map<TbResourceId, TbResourceInfo> getUsedResources(TenantId tenantId, JsonNode jsonNode, Map<String, String> mapping) {
|
||||
private Map<TbResourceId, TbResourceInfo> getUsedResources(TenantId tenantId, List<JsonNode> jsonNodes, List<Map<String, String>> mappings) {
|
||||
Map<TbResourceId, TbResourceInfo> resources = new HashMap<>();
|
||||
processResources(jsonNode, mapping, value -> {
|
||||
log.trace("[{}] getUsedResources for {}", tenantId, jsonNodes);
|
||||
processResources(jsonNodes, mappings, value -> {
|
||||
String link = getResourceLink(value);
|
||||
if (link == null) {
|
||||
return value;
|
||||
@ -517,32 +537,54 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
|
||||
}
|
||||
}
|
||||
|
||||
private boolean processResources(JsonNode jsonNode, Map<String, String> mapping, UnaryOperator<String> processor) {
|
||||
private boolean processResources(List<JsonNode> jsonNodes, List<Map<String, String>> mappings, UnaryOperator<String> processor) {
|
||||
AtomicBoolean updated = new AtomicBoolean(false);
|
||||
JacksonUtil.replaceByMapping(jsonNode, mapping, Collections.emptyMap(), (name, urlNode) -> {
|
||||
String value = null;
|
||||
if (urlNode.isTextual()) { // link is in the right place
|
||||
value = urlNode.asText();
|
||||
} else {
|
||||
JsonNode id = urlNode.get("id"); // old structure is used
|
||||
if (id != null && id.isTextual()) {
|
||||
value = id.asText();
|
||||
|
||||
for (int i = 0; i < jsonNodes.size(); i++) {
|
||||
JsonNode jsonNode = jsonNodes.get(i);
|
||||
// processing by mappings first
|
||||
JacksonUtil.replaceByMapping(jsonNode, mappings.get(i), Collections.emptyMap(), (name, urlNode) -> {
|
||||
String value = null;
|
||||
if (urlNode.isTextual()) { // link is in the right place
|
||||
value = urlNode.asText();
|
||||
} else {
|
||||
JsonNode id = urlNode.get("id"); // old structure is used
|
||||
if (id != null && id.isTextual()) {
|
||||
value = id.asText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
value = processor.apply(value);
|
||||
} else {
|
||||
value = "";
|
||||
}
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
value = processor.apply(value);
|
||||
} else {
|
||||
value = "";
|
||||
}
|
||||
|
||||
JsonNode newValue = new TextNode(value);
|
||||
if (!newValue.toString().equals(urlNode.toString())) {
|
||||
updated.set(true);
|
||||
log.trace("Replaced by mapping '{}' ({}) with '{}'", value, name, newValue);
|
||||
}
|
||||
return newValue;
|
||||
});
|
||||
|
||||
// processing all
|
||||
JacksonUtil.replaceAll(jsonNode, "", (name, value) -> {
|
||||
if (!StringUtils.startsWith(value, DataConstants.TB_RESOURCE_PREFIX + "/api/resource/")) {
|
||||
return value;
|
||||
}
|
||||
|
||||
String newValue = processor.apply(value);
|
||||
if (StringUtils.equals(value, newValue)) {
|
||||
return value;
|
||||
} else {
|
||||
updated.set(true);
|
||||
log.trace("Replaced '{}' ({}) with '{}'", value, name, newValue);
|
||||
return newValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
JsonNode newValue = new TextNode(value);
|
||||
if (!newValue.toString().equals(urlNode.toString())) {
|
||||
updated.set(true);
|
||||
log.trace("Replaced '{}' with '{}'", urlNode, newValue);
|
||||
}
|
||||
return newValue;
|
||||
});
|
||||
return updated.get();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user