Introduce ResourceSubType for image resources.
This commit is contained in:
parent
45d071538c
commit
7d0e5b330b
32
application/src/main/data/upgrade/3.7.0/schema_update.sql
Normal file
32
application/src/main/data/upgrade/3.7.0/schema_update.sql
Normal file
@ -0,0 +1,32 @@
|
||||
--
|
||||
-- Copyright © 2016-2024 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.
|
||||
--
|
||||
|
||||
-- UPDATE RESOURCE SUB TYPE START
|
||||
|
||||
DO
|
||||
$$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT FROM information_schema.columns
|
||||
WHERE table_name = 'resource' AND column_name = 'resource_sub_type'
|
||||
) THEN
|
||||
ALTER TABLE resource ADD COLUMN resource_sub_type varchar(32);
|
||||
UPDATE resource SET resource_sub_type = 'IMAGE' WHERE resource_type = 'IMAGE';
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- UPDATE RESOURCE SUB TYPE END
|
||||
@ -115,6 +115,8 @@ public class ControllerConstants {
|
||||
protected static final String RESOURCE_INFO_DESCRIPTION = "Resource Info is a lightweight object that includes main information about the Resource excluding the heavyweight data. ";
|
||||
protected static final String RESOURCE_DESCRIPTION = "Resource is a heavyweight object that includes main information about the Resource and also data. ";
|
||||
|
||||
protected static final String RESOURCE_IMAGE_SUB_TYPE_DESCRIPTION = "A string value representing resource sub-type.";
|
||||
|
||||
protected static final String RESOURCE_INCLUDE_SYSTEM_IMAGES_DESCRIPTION = "Use 'true' to include system images. Disabled by default. Ignored for requests by users with system administrator authority.";
|
||||
|
||||
protected static final String RESOURCE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'substring' filter based on the resource title.";
|
||||
|
||||
@ -40,6 +40,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.thingsboard.server.common.data.ImageDescriptor;
|
||||
import org.thingsboard.server.common.data.ImageExportData;
|
||||
import org.thingsboard.server.common.data.ResourceSubType;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.TbImageDeleteResult;
|
||||
import org.thingsboard.server.common.data.TbResource;
|
||||
@ -64,6 +65,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
|
||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
|
||||
import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_IMAGE_SUB_TYPE_DESCRIPTION;
|
||||
import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_INCLUDE_SYSTEM_IMAGES_DESCRIPTION;
|
||||
import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_TEXT_SEARCH_DESCRIPTION;
|
||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
|
||||
@ -95,7 +97,8 @@ public class ImageController extends BaseController {
|
||||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
|
||||
@PostMapping("/api/image")
|
||||
public TbResourceInfo uploadImage(@RequestPart MultipartFile file,
|
||||
@RequestPart(required = false) String title) throws Exception {
|
||||
@RequestPart(required = false) String title,
|
||||
@RequestPart(required = false) String imageSubType) throws Exception {
|
||||
SecurityUser user = getCurrentUser();
|
||||
TbResource image = new TbResource();
|
||||
image.setTenantId(user.getTenantId());
|
||||
@ -108,7 +111,14 @@ public class ImageController extends BaseController {
|
||||
} else {
|
||||
image.setTitle(file.getOriginalFilename());
|
||||
}
|
||||
|
||||
ResourceSubType subType = ResourceSubType.IMAGE;
|
||||
if (StringUtils.isNotEmpty(imageSubType)) {
|
||||
subType = ResourceSubType.valueOf(imageSubType);
|
||||
}
|
||||
|
||||
image.setResourceType(ResourceType.IMAGE);
|
||||
image.setResourceSubType(subType);
|
||||
ImageDescriptor descriptor = new ImageDescriptor();
|
||||
descriptor.setMediaType(file.getContentType());
|
||||
image.setDescriptorValue(descriptor);
|
||||
@ -193,6 +203,7 @@ public class ImageController extends BaseController {
|
||||
.mediaType(descriptor.getMediaType())
|
||||
.fileName(imageInfo.getFileName())
|
||||
.title(imageInfo.getTitle())
|
||||
.subType(imageInfo.getResourceSubType().name())
|
||||
.resourceKey(imageInfo.getResourceKey())
|
||||
.isPublic(imageInfo.isPublic())
|
||||
.publicResourceKey(imageInfo.getPublicResourceKey())
|
||||
@ -214,6 +225,11 @@ public class ImageController extends BaseController {
|
||||
} else {
|
||||
image.setTitle(imageData.getFileName());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(imageData.getSubType())) {
|
||||
image.setResourceSubType(ResourceSubType.valueOf(imageData.getSubType()));
|
||||
} else {
|
||||
image.setResourceSubType(ResourceSubType.IMAGE);
|
||||
}
|
||||
image.setResourceType(ResourceType.IMAGE);
|
||||
image.setResourceKey(imageData.getResourceKey());
|
||||
image.setPublic(imageData.isPublic());
|
||||
@ -250,6 +266,8 @@ public class ImageController extends BaseController {
|
||||
@RequestParam int pageSize,
|
||||
@Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true)
|
||||
@RequestParam int page,
|
||||
@Parameter(description = RESOURCE_IMAGE_SUB_TYPE_DESCRIPTION, schema = @Schema(allowableValues = {"IMAGE", "IOT_SVG"}))
|
||||
@RequestParam(required = false) String imageSubType,
|
||||
@Parameter(description = RESOURCE_INCLUDE_SYSTEM_IMAGES_DESCRIPTION)
|
||||
@RequestParam(required = false) boolean includeSystemImages,
|
||||
@Parameter(description = RESOURCE_TEXT_SEARCH_DESCRIPTION)
|
||||
@ -261,10 +279,14 @@ public class ImageController extends BaseController {
|
||||
// PE: generic permission
|
||||
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
|
||||
TenantId tenantId = getTenantId();
|
||||
ResourceSubType subType = ResourceSubType.IMAGE;
|
||||
if (StringUtils.isNotEmpty(imageSubType)) {
|
||||
subType = ResourceSubType.valueOf(imageSubType);
|
||||
}
|
||||
if (getCurrentUser().getAuthority() == Authority.SYS_ADMIN || !includeSystemImages) {
|
||||
return checkNotNull(imageService.getImagesByTenantId(tenantId, pageLink));
|
||||
return checkNotNull(imageService.getImagesByTenantId(tenantId, subType, pageLink));
|
||||
} else {
|
||||
return checkNotNull(imageService.getAllImagesByTenantId(tenantId, pageLink));
|
||||
return checkNotNull(imageService.getAllImagesByTenantId(tenantId, subType, pageLink));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -137,6 +137,10 @@ public class ThingsboardInstallService {
|
||||
entityDatabaseSchemaService.createCustomerTitleUniqueConstraintIfNotExists();
|
||||
systemDataLoaderService.updateDefaultNotificationConfigs(false);
|
||||
systemDataLoaderService.updateJwtSettings();
|
||||
break;
|
||||
case "3.7.0":
|
||||
log.info("Upgrading ThingsBoard from version 3.7.0 to 3.7.1 ...");
|
||||
databaseEntitiesUpgradeService.upgradeDatabase("3.7.0");
|
||||
//TODO DON'T FORGET to update switch statement in the CacheCleanupService if you need to clear the cache
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -121,6 +121,9 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
|
||||
case "3.6.4":
|
||||
updateSchema("3.6.4", 3006004, "3.7.0", 3007000, null);
|
||||
break;
|
||||
case "3.7.0":
|
||||
updateSchema("3.7.0", 3007000, "3.7.1", 3007001, null);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
|
||||
}
|
||||
|
||||
@ -23,11 +23,14 @@ import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.mock.web.MockPart;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.common.data.ImageDescriptor;
|
||||
import org.thingsboard.server.common.data.ImageExportData;
|
||||
import org.thingsboard.server.common.data.ResourceSubType;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.StringUtils;
|
||||
import org.thingsboard.server.common.data.SystemParams;
|
||||
import org.thingsboard.server.common.data.TbResourceInfo;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
@ -35,6 +38,7 @@ import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.dao.service.DaoSqlTest;
|
||||
import org.thingsboard.server.dao.sql.resource.TbResourceRepository;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
@ -53,6 +57,7 @@ public class ImageControllerTest extends AbstractControllerTest {
|
||||
|
||||
@Before
|
||||
public void beforeEach() throws Exception {
|
||||
resourceRepository.deleteAll();
|
||||
loginTenantAdmin();
|
||||
}
|
||||
|
||||
@ -66,6 +71,8 @@ public class ImageControllerTest extends AbstractControllerTest {
|
||||
String filename = "my_png_image.png";
|
||||
TbResourceInfo imageInfo = uploadImage(HttpMethod.POST, "/api/image", filename, "image/png", PNG_IMAGE);
|
||||
|
||||
assertThat(imageInfo.getResourceSubType()).isEqualTo(ResourceSubType.IMAGE);
|
||||
|
||||
assertThat(imageInfo.getTitle()).isEqualTo(filename);
|
||||
assertThat(imageInfo.getResourceType()).isEqualTo(ResourceType.IMAGE);
|
||||
assertThat(imageInfo.getResourceKey()).isEqualTo(filename);
|
||||
@ -85,6 +92,8 @@ public class ImageControllerTest extends AbstractControllerTest {
|
||||
String filename = "my_jpeg_image.jpg";
|
||||
TbResourceInfo imageInfo = uploadImage(HttpMethod.POST, "/api/image", filename, "image/jpeg", JPEG_IMAGE);
|
||||
|
||||
assertThat(imageInfo.getResourceSubType()).isEqualTo(ResourceSubType.IMAGE);
|
||||
|
||||
ImageDescriptor imageDescriptor = imageInfo.getDescriptor(ImageDescriptor.class);
|
||||
checkJpegImageDescriptor(imageDescriptor);
|
||||
|
||||
@ -97,6 +106,22 @@ public class ImageControllerTest extends AbstractControllerTest {
|
||||
String filename = "my_svg_image.svg";
|
||||
TbResourceInfo imageInfo = uploadImage(HttpMethod.POST, "/api/image", filename, "image/svg+xml", SVG_IMAGE);
|
||||
|
||||
assertThat(imageInfo.getResourceSubType()).isEqualTo(ResourceSubType.IMAGE);
|
||||
|
||||
ImageDescriptor imageDescriptor = imageInfo.getDescriptor(ImageDescriptor.class);
|
||||
checkSvgImageDescriptor(imageDescriptor);
|
||||
|
||||
assertThat(downloadImage("tenant", filename)).containsExactly(SVG_IMAGE);
|
||||
assertThat(downloadImagePreview("tenant", filename)).hasSize((int) imageDescriptor.getPreviewDescriptor().getSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUploadIoTSvgImage() throws Exception {
|
||||
String filename = "my_iot_svg_image.svg";
|
||||
TbResourceInfo imageInfo = uploadImage(HttpMethod.POST, "/api/image", ResourceSubType.IOT_SVG.name(), filename, "image/svg+xml", SVG_IMAGE);
|
||||
|
||||
assertThat(imageInfo.getResourceSubType()).isEqualTo(ResourceSubType.IOT_SVG);
|
||||
|
||||
ImageDescriptor imageDescriptor = imageInfo.getDescriptor(ImageDescriptor.class);
|
||||
checkSvgImageDescriptor(imageDescriptor);
|
||||
|
||||
@ -175,6 +200,7 @@ public class ImageControllerTest extends AbstractControllerTest {
|
||||
assertThat(exportData.getMediaType()).isEqualTo("image/png");
|
||||
assertThat(exportData.getFileName()).isEqualTo(filename);
|
||||
assertThat(exportData.getTitle()).isEqualTo(filename);
|
||||
assertThat(exportData.getSubType()).isEqualTo(ResourceSubType.IMAGE.name());
|
||||
assertThat(exportData.getResourceKey()).isEqualTo(filename);
|
||||
assertThat(exportData.getData()).isEqualTo(Base64.getEncoder().encodeToString(PNG_IMAGE));
|
||||
assertThat(exportData.isPublic()).isTrue();
|
||||
@ -184,6 +210,7 @@ public class ImageControllerTest extends AbstractControllerTest {
|
||||
|
||||
TbResourceInfo importedImageInfo = doPut("/api/image/import", exportData, TbResourceInfo.class);
|
||||
assertThat(importedImageInfo.getTitle()).isEqualTo(filename);
|
||||
assertThat(exportData.getSubType()).isEqualTo(ResourceSubType.IMAGE.name());
|
||||
assertThat(importedImageInfo.getResourceKey()).isEqualTo(filename);
|
||||
assertThat(importedImageInfo.getFileName()).isEqualTo(filename);
|
||||
assertThat(importedImageInfo.isPublic()).isTrue();
|
||||
@ -198,20 +225,37 @@ public class ImageControllerTest extends AbstractControllerTest {
|
||||
String systemImageName = "my_system_png_image.png";
|
||||
TbResourceInfo systemImage = uploadImage(HttpMethod.POST, "/api/image", systemImageName, "image/png", PNG_IMAGE);
|
||||
|
||||
String systemIotSvgName = "my_system_iot_svg_image.svg";
|
||||
TbResourceInfo systemIotSvg = uploadImage(HttpMethod.POST, "/api/image", ResourceSubType.IOT_SVG.name(), systemIotSvgName, "image/svg+xml", SVG_IMAGE);
|
||||
|
||||
loginTenantAdmin();
|
||||
String tenantImageName = "my_jpeg_image.jpg";
|
||||
TbResourceInfo tenantImage = uploadImage(HttpMethod.POST, "/api/image", tenantImageName, "image/jpeg", JPEG_IMAGE);
|
||||
|
||||
String tenantIotSvgName = "my_iot_svg_image.svg";
|
||||
TbResourceInfo tenantIotSvg = uploadImage(HttpMethod.POST, "/api/image", ResourceSubType.IOT_SVG.name(), tenantIotSvgName, "image/svg+xml", SVG_IMAGE);
|
||||
|
||||
List<TbResourceInfo> tenantImages = getImages(null, false, 10);
|
||||
assertThat(tenantImages).containsOnly(tenantImage);
|
||||
|
||||
List<TbResourceInfo> tenantIotSvgs = getImages(null, ResourceSubType.IOT_SVG.name(), false, 10);
|
||||
assertThat(tenantIotSvgs).containsOnly(tenantIotSvg);
|
||||
|
||||
List<TbResourceInfo> allImages = getImages(null, true, 10);
|
||||
assertThat(allImages).containsOnly(tenantImage, systemImage);
|
||||
|
||||
List<TbResourceInfo> allIotSvgs = getImages(null, ResourceSubType.IOT_SVG.name(), true, 10);
|
||||
assertThat(allIotSvgs).containsOnly(tenantIotSvg, systemIotSvg);
|
||||
|
||||
assertThat(getImages("png", true, 10))
|
||||
.containsOnly(systemImage);
|
||||
assertThat(getImages("jpg", true, 10))
|
||||
.containsOnly(tenantImage);
|
||||
|
||||
assertThat(getImages("my_system_iot", ResourceSubType.IOT_SVG.name(), true, 10))
|
||||
.containsOnly(systemIotSvg);
|
||||
assertThat(getImages("my_iot_svg", ResourceSubType.IOT_SVG.name(),true, 10))
|
||||
.containsOnly(tenantIotSvg);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -312,7 +356,15 @@ public class ImageControllerTest extends AbstractControllerTest {
|
||||
}
|
||||
|
||||
private List<TbResourceInfo> getImages(String searchText, boolean includeSystemImages, int limit) throws Exception {
|
||||
PageData<TbResourceInfo> images = doGetTypedWithPageLink("/api/images?includeSystemImages=" + includeSystemImages + "&", new TypeReference<>() {}, new PageLink(limit, 0, searchText));
|
||||
return this.getImages(searchText, null, includeSystemImages, limit);
|
||||
}
|
||||
|
||||
private List<TbResourceInfo> getImages(String searchText, String imageSubType, boolean includeSystemImages, int limit) throws Exception {
|
||||
var url = "/api/images?includeSystemImages=" + includeSystemImages + "&";
|
||||
if (StringUtils.isNotEmpty(imageSubType)) {
|
||||
url += "imageSubType=" + imageSubType+ "&";
|
||||
}
|
||||
PageData<TbResourceInfo> images = doGetTypedWithPageLink(url, new TypeReference<>() {}, new PageLink(limit, 0, searchText));
|
||||
return images.getData();
|
||||
}
|
||||
|
||||
@ -332,8 +384,16 @@ public class ImageControllerTest extends AbstractControllerTest {
|
||||
}
|
||||
|
||||
private <R> TbResourceInfo uploadImage(HttpMethod httpMethod, String url, String filename, String mediaType, byte[] content) throws Exception {
|
||||
return this.uploadImage(httpMethod, url, null, filename, mediaType, content);
|
||||
}
|
||||
|
||||
private <R> TbResourceInfo uploadImage(HttpMethod httpMethod, String url, String subType, String filename, String mediaType, byte[] content) throws Exception {
|
||||
MockMultipartFile file = new MockMultipartFile("file", filename, mediaType, content);
|
||||
var request = MockMvcRequestBuilders.multipart(httpMethod, url).file(file);
|
||||
if (StringUtils.isNotEmpty(subType)) {
|
||||
var imageSubTypePart = new MockPart("imageSubType", subType.getBytes(StandardCharsets.UTF_8));
|
||||
request.part(imageSubTypePart);
|
||||
}
|
||||
setJwtToken(request);
|
||||
return readResponse(mockMvc.perform(request).andExpect(status().isOk()), TbResourceInfo.class);
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ package org.thingsboard.server.dao.resource;
|
||||
|
||||
import org.thingsboard.server.common.data.Dashboard;
|
||||
import org.thingsboard.server.common.data.HasImage;
|
||||
import org.thingsboard.server.common.data.ResourceSubType;
|
||||
import org.thingsboard.server.common.data.TbImageDeleteResult;
|
||||
import org.thingsboard.server.common.data.TbResource;
|
||||
import org.thingsboard.server.common.data.TbResourceInfo;
|
||||
@ -36,9 +37,9 @@ public interface ImageService {
|
||||
|
||||
TbResourceInfo getPublicImageInfoByKey(String publicResourceKey);
|
||||
|
||||
PageData<TbResourceInfo> getImagesByTenantId(TenantId tenantId, PageLink pageLink);
|
||||
PageData<TbResourceInfo> getImagesByTenantId(TenantId tenantId, ResourceSubType imageSubType, PageLink pageLink);
|
||||
|
||||
PageData<TbResourceInfo> getAllImagesByTenantId(TenantId tenantId, PageLink pageLink);
|
||||
PageData<TbResourceInfo> getAllImagesByTenantId(TenantId tenantId, ResourceSubType imageSubType, PageLink pageLink);
|
||||
|
||||
byte[] getImageData(TenantId tenantId, TbResourceId imageId);
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@ public class ImageExportData {
|
||||
private String mediaType;
|
||||
private String fileName;
|
||||
private String title;
|
||||
private String subType;
|
||||
private String resourceKey;
|
||||
private boolean isPublic;
|
||||
private String publicResourceKey;
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
package org.thingsboard.server.common.data;
|
||||
|
||||
public enum ResourceSubType {
|
||||
IMAGE,
|
||||
IOT_SVG
|
||||
}
|
||||
@ -46,6 +46,8 @@ public class TbResourceInfo extends BaseData<TbResourceId> implements HasName, H
|
||||
private String title;
|
||||
@Schema(description = "Resource type.", example = "LWM2M_MODEL", accessMode = Schema.AccessMode.READ_ONLY)
|
||||
private ResourceType resourceType;
|
||||
@Schema(description = "Resource sub type.", example = "IOT_SVG", accessMode = Schema.AccessMode.READ_ONLY)
|
||||
private ResourceSubType resourceSubType;
|
||||
@NoXss
|
||||
@Length(fieldName = "resourceKey")
|
||||
@Schema(description = "Resource key.", example = "19_1.0", accessMode = Schema.AccessMode.READ_ONLY)
|
||||
@ -78,6 +80,7 @@ public class TbResourceInfo extends BaseData<TbResourceId> implements HasName, H
|
||||
this.tenantId = resourceInfo.tenantId;
|
||||
this.title = resourceInfo.title;
|
||||
this.resourceType = resourceInfo.resourceType;
|
||||
this.resourceSubType = resourceInfo.resourceSubType;
|
||||
this.resourceKey = resourceInfo.resourceKey;
|
||||
this.searchText = resourceInfo.searchText;
|
||||
this.isPublic = resourceInfo.isPublic;
|
||||
|
||||
@ -27,5 +27,6 @@ public class TbResourceInfoFilter {
|
||||
|
||||
private TenantId tenantId;
|
||||
private Set<ResourceType> resourceTypes;
|
||||
private Set<ResourceSubType> resourceSubTypes;
|
||||
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.DeviceProfileProvisionType;
|
||||
import org.thingsboard.server.common.data.DeviceProfileType;
|
||||
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.ResourceSubType;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.TbResource;
|
||||
import org.thingsboard.server.common.data.Tenant;
|
||||
@ -827,6 +828,9 @@ public class ProtoUtils {
|
||||
if (isNotNull(resource.getPreview())) {
|
||||
builder.setPreview(ByteString.copyFrom(resource.getPreview()));
|
||||
}
|
||||
if (isNotNull(resource.getResourceSubType())) {
|
||||
builder.setResourceSubType(resource.getResourceSubType().name());
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@ -858,6 +862,9 @@ public class ProtoUtils {
|
||||
if (proto.hasPreview()) {
|
||||
resource.setPreview(proto.getPreview().toByteArray());
|
||||
}
|
||||
if (proto.hasResourceSubType()) {
|
||||
resource.setResourceSubType(ResourceSubType.valueOf(proto.getResourceSubType()));
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
|
||||
|
||||
@ -286,6 +286,7 @@ message TbResourceProto {
|
||||
optional int64 externalIdLSB = 16;
|
||||
optional bytes data = 17;
|
||||
optional bytes preview = 18;
|
||||
optional string resourceSubType = 19;
|
||||
}
|
||||
|
||||
message ApiUsageStateProto {
|
||||
|
||||
@ -498,6 +498,7 @@ public class ModelConstants {
|
||||
public static final String RESOURCE_TABLE_NAME = "resource";
|
||||
public static final String RESOURCE_TENANT_ID_COLUMN = TENANT_ID_COLUMN;
|
||||
public static final String RESOURCE_TYPE_COLUMN = "resource_type";
|
||||
public static final String RESOURCE_SUB_TYPE_COLUMN = "resource_sub_type";
|
||||
public static final String RESOURCE_KEY_COLUMN = "resource_key";
|
||||
public static final String RESOURCE_TITLE_COLUMN = TITLE_PROPERTY;
|
||||
public static final String RESOURCE_FILE_NAME_COLUMN = "file_name";
|
||||
|
||||
@ -20,6 +20,7 @@ import jakarta.persistence.Convert;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.thingsboard.server.common.data.ResourceSubType;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.TbResource;
|
||||
import org.thingsboard.server.common.data.id.TbResourceId;
|
||||
@ -42,6 +43,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_IS_PUBLIC
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_KEY_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_PREVIEW_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.PUBLIC_RESOURCE_KEY_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_SUB_TYPE_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TABLE_NAME;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TENANT_ID_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TITLE_COLUMN;
|
||||
@ -63,6 +65,9 @@ public class TbResourceEntity extends BaseSqlEntity<TbResource> {
|
||||
@Column(name = RESOURCE_TYPE_COLUMN)
|
||||
private String resourceType;
|
||||
|
||||
@Column(name = RESOURCE_SUB_TYPE_COLUMN)
|
||||
private String resourceSubType;
|
||||
|
||||
@Column(name = RESOURCE_KEY_COLUMN)
|
||||
private String resourceKey;
|
||||
|
||||
@ -107,6 +112,9 @@ public class TbResourceEntity extends BaseSqlEntity<TbResource> {
|
||||
}
|
||||
this.title = resource.getTitle();
|
||||
this.resourceType = resource.getResourceType().name();
|
||||
if (resource.getResourceSubType() != null) {
|
||||
this.resourceSubType = resource.getResourceSubType().name();
|
||||
}
|
||||
this.resourceKey = resource.getResourceKey();
|
||||
this.searchText = resource.getSearchText();
|
||||
this.fileName = resource.getFileName();
|
||||
@ -126,6 +134,7 @@ public class TbResourceEntity extends BaseSqlEntity<TbResource> {
|
||||
resource.setTenantId(TenantId.fromUUID(tenantId));
|
||||
resource.setTitle(title);
|
||||
resource.setResourceType(ResourceType.valueOf(resourceType));
|
||||
resource.setResourceSubType(resourceSubType != null ? ResourceSubType.valueOf(resourceSubType) : null);
|
||||
resource.setResourceKey(resourceKey);
|
||||
resource.setSearchText(searchText);
|
||||
resource.setFileName(fileName);
|
||||
|
||||
@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import jakarta.persistence.Convert;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.thingsboard.server.common.data.ResourceSubType;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.TbResourceInfo;
|
||||
import org.thingsboard.server.common.data.id.TbResourceId;
|
||||
@ -39,6 +40,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_FILE_NAME
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_IS_PUBLIC_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_KEY_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.PUBLIC_RESOURCE_KEY_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_SUB_TYPE_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TABLE_NAME;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TENANT_ID_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TITLE_COLUMN;
|
||||
@ -60,6 +62,9 @@ public class TbResourceInfoEntity extends BaseSqlEntity<TbResourceInfo> implemen
|
||||
@Column(name = RESOURCE_TYPE_COLUMN)
|
||||
private String resourceType;
|
||||
|
||||
@Column(name = RESOURCE_SUB_TYPE_COLUMN)
|
||||
private String resourceSubType;
|
||||
|
||||
@Column(name = RESOURCE_KEY_COLUMN)
|
||||
private String resourceKey;
|
||||
|
||||
@ -96,6 +101,9 @@ public class TbResourceInfoEntity extends BaseSqlEntity<TbResourceInfo> implemen
|
||||
this.tenantId = resource.getTenantId().getId();
|
||||
this.title = resource.getTitle();
|
||||
this.resourceType = resource.getResourceType().name();
|
||||
if (resource.getResourceSubType() != null) {
|
||||
this.resourceSubType = resource.getResourceSubType().name();
|
||||
}
|
||||
this.resourceKey = resource.getResourceKey();
|
||||
this.searchText = resource.getSearchText();
|
||||
this.etag = resource.getEtag();
|
||||
@ -113,6 +121,7 @@ public class TbResourceInfoEntity extends BaseSqlEntity<TbResourceInfo> implemen
|
||||
resource.setTenantId(TenantId.fromUUID(tenantId));
|
||||
resource.setTitle(title);
|
||||
resource.setResourceType(ResourceType.valueOf(resourceType));
|
||||
resource.setResourceSubType(resourceSubType != null ? ResourceSubType.valueOf(resourceSubType) : null);
|
||||
resource.setResourceKey(resourceKey);
|
||||
resource.setSearchText(searchText);
|
||||
resource.setEtag(etag);
|
||||
|
||||
@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.DataConstants;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.HasImage;
|
||||
import org.thingsboard.server.common.data.ImageDescriptor;
|
||||
import org.thingsboard.server.common.data.ResourceSubType;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.TbImageDeleteResult;
|
||||
import org.thingsboard.server.common.data.TbResource;
|
||||
@ -140,6 +141,9 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
if (image.getId() == null) {
|
||||
image.setResourceKey(getUniqueKey(image.getTenantId(), StringUtils.defaultIfEmpty(image.getResourceKey(), image.getFileName())));
|
||||
}
|
||||
if (image.getResourceSubType() == null) {
|
||||
image.setResourceSubType(ResourceSubType.IMAGE);
|
||||
}
|
||||
resourceValidator.validate(image, TbResourceInfo::getTenantId);
|
||||
|
||||
ImageDescriptor descriptor = image.getDescriptor(ImageDescriptor.class);
|
||||
@ -220,21 +224,23 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageData<TbResourceInfo> getImagesByTenantId(TenantId tenantId, PageLink pageLink) {
|
||||
public PageData<TbResourceInfo> getImagesByTenantId(TenantId tenantId, ResourceSubType imageSubType, PageLink pageLink) {
|
||||
log.trace("Executing getImagesByTenantId [{}]", tenantId);
|
||||
TbResourceInfoFilter filter = TbResourceInfoFilter.builder()
|
||||
.tenantId(tenantId)
|
||||
.resourceTypes(Set.of(ResourceType.IMAGE))
|
||||
.resourceSubTypes(Set.of(imageSubType))
|
||||
.build();
|
||||
return findTenantResourcesByTenantId(filter, pageLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageData<TbResourceInfo> getAllImagesByTenantId(TenantId tenantId, PageLink pageLink) {
|
||||
public PageData<TbResourceInfo> getAllImagesByTenantId(TenantId tenantId, ResourceSubType imageSubType, PageLink pageLink) {
|
||||
log.trace("Executing getAllImagesByTenantId [{}]", tenantId);
|
||||
TbResourceInfoFilter filter = TbResourceInfoFilter.builder()
|
||||
.tenantId(tenantId)
|
||||
.resourceTypes(Set.of(ResourceType.IMAGE))
|
||||
.resourceSubTypes(Set.of(imageSubType))
|
||||
.build();
|
||||
return findAllTenantResourcesByTenantId(filter, pageLink);
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
|
||||
public List<TbResource> findTenantResourcesByResourceTypeAndObjectIds(TenantId tenantId, ResourceType resourceType, String[] objectIds) {
|
||||
log.trace("Executing findTenantResourcesByResourceTypeAndObjectIds [{}][{}][{}]", tenantId, resourceType, objectIds);
|
||||
validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
|
||||
return resourceDao.findResourcesByTenantIdAndResourceType(tenantId, resourceType, objectIds, null);
|
||||
return resourceDao.findResourcesByTenantIdAndResourceType(tenantId, resourceType, null, objectIds, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -198,7 +198,7 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
|
||||
public PageData<TbResource> findTenantResourcesByResourceTypeAndPageLink(TenantId tenantId, ResourceType resourceType, PageLink pageLink) {
|
||||
log.trace("Executing findTenantResourcesByResourceTypeAndPageLink [{}][{}][{}]", tenantId, resourceType, pageLink);
|
||||
validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
|
||||
return resourceDao.findResourcesByTenantIdAndResourceType(tenantId, resourceType, pageLink);
|
||||
return resourceDao.findResourcesByTenantIdAndResourceType(tenantId, resourceType, null, pageLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.thingsboard.server.dao.resource;
|
||||
|
||||
import org.thingsboard.server.common.data.ResourceSubType;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.TbResource;
|
||||
import org.thingsboard.server.common.data.id.TbResourceId;
|
||||
@ -35,10 +36,12 @@ public interface TbResourceDao extends Dao<TbResource>, TenantEntityWithDataDao,
|
||||
|
||||
PageData<TbResource> findResourcesByTenantIdAndResourceType(TenantId tenantId,
|
||||
ResourceType resourceType,
|
||||
ResourceSubType resourceSubType,
|
||||
PageLink pageLink);
|
||||
|
||||
List<TbResource> findResourcesByTenantIdAndResourceType(TenantId tenantId,
|
||||
ResourceType resourceType,
|
||||
ResourceSubType resourceSubType,
|
||||
String[] objectIds,
|
||||
String searchText);
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.ResourceSubType;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.TbResource;
|
||||
import org.thingsboard.server.common.data.id.TbResourceId;
|
||||
@ -68,11 +69,13 @@ public class JpaTbResourceDao extends JpaAbstractDao<TbResourceEntity, TbResourc
|
||||
@Override
|
||||
public PageData<TbResource> findResourcesByTenantIdAndResourceType(TenantId tenantId,
|
||||
ResourceType resourceType,
|
||||
ResourceSubType resourceSubType,
|
||||
PageLink pageLink) {
|
||||
return DaoUtil.toPageData(resourceRepository.findResourcesPage(
|
||||
tenantId.getId(),
|
||||
TenantId.SYS_TENANT_ID.getId(),
|
||||
resourceType.name(),
|
||||
resourceSubType != null ? resourceSubType.name() : null,
|
||||
pageLink.getTextSearch(),
|
||||
DaoUtil.toPageable(pageLink)
|
||||
));
|
||||
@ -80,6 +83,7 @@ public class JpaTbResourceDao extends JpaAbstractDao<TbResourceEntity, TbResourc
|
||||
|
||||
@Override
|
||||
public List<TbResource> findResourcesByTenantIdAndResourceType(TenantId tenantId, ResourceType resourceType,
|
||||
ResourceSubType resourceSubType,
|
||||
String[] objectIds,
|
||||
String searchText) {
|
||||
return objectIds == null ?
|
||||
@ -87,6 +91,7 @@ public class JpaTbResourceDao extends JpaAbstractDao<TbResourceEntity, TbResourc
|
||||
tenantId.getId(),
|
||||
TenantId.SYS_TENANT_ID.getId(),
|
||||
resourceType.name(),
|
||||
resourceSubType != null ? resourceSubType.name() : null,
|
||||
searchText)) :
|
||||
DaoUtil.convertDataList(resourceRepository.findResourcesByIds(
|
||||
tenantId.getId(),
|
||||
|
||||
@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thingsboard.server.common.data.ResourceSubType;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.TbResourceInfo;
|
||||
import org.thingsboard.server.common.data.TbResourceInfoFilter;
|
||||
@ -63,10 +64,13 @@ public class JpaTbResourceInfoDao extends JpaAbstractDao<TbResourceInfoEntity, T
|
||||
if (CollectionsUtil.isEmpty(resourceTypes)) {
|
||||
resourceTypes = EnumSet.allOf(ResourceType.class);
|
||||
}
|
||||
Set<ResourceSubType> resourceSubTypes = filter.getResourceSubTypes();
|
||||
return DaoUtil.toPageData(resourceInfoRepository
|
||||
.findAllTenantResourcesByTenantId(
|
||||
filter.getTenantId().getId(), TenantId.NULL_UUID,
|
||||
resourceTypes.stream().map(Enum::name).collect(Collectors.toList()),
|
||||
CollectionsUtil.isEmpty(resourceSubTypes) ? null :
|
||||
resourceSubTypes.stream().map(Enum::name).collect(Collectors.toList()),
|
||||
Objects.toString(pageLink.getTextSearch(), ""),
|
||||
DaoUtil.toPageable(pageLink)));
|
||||
}
|
||||
@ -77,10 +81,13 @@ public class JpaTbResourceInfoDao extends JpaAbstractDao<TbResourceInfoEntity, T
|
||||
if (CollectionsUtil.isEmpty(resourceTypes)) {
|
||||
resourceTypes = EnumSet.allOf(ResourceType.class);
|
||||
}
|
||||
Set<ResourceSubType> resourceSubTypes = filter.getResourceSubTypes();
|
||||
return DaoUtil.toPageData(resourceInfoRepository
|
||||
.findTenantResourcesByTenantId(
|
||||
filter.getTenantId().getId(),
|
||||
resourceTypes.stream().map(Enum::name).collect(Collectors.toList()),
|
||||
CollectionsUtil.isEmpty(resourceSubTypes) ? null :
|
||||
resourceSubTypes.stream().map(Enum::name).collect(Collectors.toList()),
|
||||
pageLink.getTextSearch(),
|
||||
DaoUtil.toPageable(pageLink)));
|
||||
}
|
||||
|
||||
@ -37,19 +37,23 @@ public interface TbResourceInfoRepository extends JpaRepository<TbResourceInfoEn
|
||||
"WHERE sr.tenantId = :tenantId " +
|
||||
"AND tr.resourceType = sr.resourceType " +
|
||||
"AND tr.resourceKey = sr.resourceKey)))" +
|
||||
"AND tr.resourceType IN :resourceTypes")
|
||||
"AND tr.resourceType IN :resourceTypes " +
|
||||
"AND (:resourceSubTypes IS NULL OR tr.resourceSubType IN :resourceSubTypes)")
|
||||
Page<TbResourceInfoEntity> findAllTenantResourcesByTenantId(@Param("tenantId") UUID tenantId,
|
||||
@Param("systemTenantId") UUID systemTenantId,
|
||||
@Param("resourceTypes") List<String> resourceTypes,
|
||||
@Param("resourceSubTypes") List<String> resourceSubTypes,
|
||||
@Param("searchText") String searchText,
|
||||
Pageable pageable);
|
||||
|
||||
@Query("SELECT ri FROM TbResourceInfoEntity ri WHERE " +
|
||||
"ri.tenantId = :tenantId " +
|
||||
"AND ri.resourceType IN :resourceTypes " +
|
||||
"AND (:resourceSubTypes IS NULL OR ri.resourceSubType IN :resourceSubTypes) " +
|
||||
"AND (:searchText IS NULL OR ilike(ri.title, CONCAT('%', :searchText, '%')) = true)")
|
||||
Page<TbResourceInfoEntity> findTenantResourcesByTenantId(@Param("tenantId") UUID tenantId,
|
||||
@Param("resourceTypes") List<String> resourceTypes,
|
||||
@Param("resourceSubTypes") List<String> resourceSubTypes,
|
||||
@Param("searchText") String searchText,
|
||||
Pageable pageable);
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@ public interface TbResourceRepository extends JpaRepository<TbResourceEntity, UU
|
||||
|
||||
@Query("SELECT tr FROM TbResourceEntity tr " +
|
||||
"WHERE tr.resourceType = :resourceType " +
|
||||
"AND (:resourceSubType IS NULL OR tr.resourceSubType = :resourceSubType) " +
|
||||
"AND (:searchText IS NULL OR ilike(tr.searchText, CONCAT('%', :searchText, '%')) = true) " +
|
||||
"AND (tr.tenantId = :tenantId " +
|
||||
"OR (tr.tenantId = :systemAdminId " +
|
||||
@ -46,11 +47,13 @@ public interface TbResourceRepository extends JpaRepository<TbResourceEntity, UU
|
||||
@Param("tenantId") UUID tenantId,
|
||||
@Param("systemAdminId") UUID sysAdminId,
|
||||
@Param("resourceType") String resourceType,
|
||||
@Param("resourceSubType") String resourceSubType,
|
||||
@Param("searchText") String searchText,
|
||||
Pageable pageable);
|
||||
|
||||
@Query("SELECT tr FROM TbResourceEntity tr " +
|
||||
"WHERE tr.resourceType = :resourceType " +
|
||||
"AND (:resourceSubType IS NULL OR tr.resourceSubType = :resourceSubType) " +
|
||||
"AND (:searchText IS NULL OR ilike(tr.searchText, CONCAT('%', :searchText, '%')) = true) " +
|
||||
"AND (tr.tenantId = :tenantId " +
|
||||
"OR (tr.tenantId = :systemAdminId " +
|
||||
@ -62,6 +65,7 @@ public interface TbResourceRepository extends JpaRepository<TbResourceEntity, UU
|
||||
List<TbResourceEntity> findResources(@Param("tenantId") UUID tenantId,
|
||||
@Param("systemAdminId") UUID sysAdminId,
|
||||
@Param("resourceType") String resourceType,
|
||||
@Param("resourceSubType") String resourceSubType,
|
||||
@Param("searchText") String searchText);
|
||||
|
||||
@Query("SELECT tr FROM TbResourceEntity tr " +
|
||||
|
||||
@ -715,6 +715,7 @@ CREATE TABLE IF NOT EXISTS resource (
|
||||
tenant_id uuid NOT NULL,
|
||||
title varchar(255) NOT NULL,
|
||||
resource_type varchar(32) NOT NULL,
|
||||
resource_sub_type varchar(32),
|
||||
resource_key varchar(255) NOT NULL,
|
||||
search_text varchar(255),
|
||||
file_name varchar(255) NOT NULL,
|
||||
|
||||
@ -58,6 +58,7 @@ import org.thingsboard.server.common.data.EventInfo;
|
||||
import org.thingsboard.server.common.data.ImageExportData;
|
||||
import org.thingsboard.server.common.data.OtaPackage;
|
||||
import org.thingsboard.server.common.data.OtaPackageInfo;
|
||||
import org.thingsboard.server.common.data.ResourceSubType;
|
||||
import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest;
|
||||
import org.thingsboard.server.common.data.StringUtils;
|
||||
import org.thingsboard.server.common.data.SystemInfo;
|
||||
@ -3603,10 +3604,19 @@ public class RestClient implements Closeable {
|
||||
}
|
||||
|
||||
public PageData<TbResourceInfo> getImages(PageLink pageLink, boolean includeSystemImages) {
|
||||
return this.getImages(pageLink, null, includeSystemImages);
|
||||
}
|
||||
|
||||
public PageData<TbResourceInfo> getImages(PageLink pageLink, ResourceSubType imageSubType, boolean includeSystemImages) {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
var url = baseURL + "/api/images?includeSystemImages={includeSystemImages}&";
|
||||
addPageLinkToParam(params, pageLink);
|
||||
params.put("includeSystemImages", String.valueOf(includeSystemImages));
|
||||
return restTemplate.exchange(baseURL + "/api/images?includeSystemImages={includeSystemImages}&" + getUrlParams(pageLink),
|
||||
if (imageSubType != null) {
|
||||
url += "imageSubType={imageSubType}&";
|
||||
params.put("imageSubType", imageSubType.name());
|
||||
}
|
||||
return restTemplate.exchange(url + getUrlParams(pageLink),
|
||||
HttpMethod.GET,
|
||||
HttpEntity.EMPTY,
|
||||
new ParameterizedTypeReference<PageData<TbResourceInfo>>() {},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user