diff --git a/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java b/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java index 697f1bdcf..13f8e43ae 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java +++ b/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java @@ -48,6 +48,14 @@ private ProductDetailModel createModel(Product product, String version, String r ProductDetailModel model = instantiateModel(product); productModelAssembler.createResource(model, product); String productId = Optional.of(product).map(Product::getId).orElse(StringUtils.EMPTY); + + if (requestPath.equals(RequestMappingConstants.BEST_MATCH_BY_ID_AND_VERSION)) { + String bestMatchVersion = VersionUtils.getBestMatchVersion(product.getReleasedVersions(), version); + Link link = linkTo( + methodOn(ProductDetailsController.class).findProductJsonContent(productId, bestMatchVersion)).withSelfRel(); + model.setMetaProductJsonUrl(link.getHref()); + } + selfLinkWithTag = switch (requestPath) { case RequestMappingConstants.BEST_MATCH_BY_ID_AND_VERSION -> methodOn(ProductDetailsController.class).findBestMatchProductDetailsByVersion(productId, version); @@ -56,16 +64,6 @@ private ProductDetailModel createModel(Product product, String version, String r default -> methodOn(ProductDetailsController.class).findProductDetails(productId); }; - try { - if (requestPath.equals(RequestMappingConstants.BEST_MATCH_BY_ID_AND_VERSION)) { - String bestMatchVersion = VersionUtils.getBestMatchVersion(product.getReleasedVersions(), version); - Link link = linkTo( - methodOn(ProductDetailsController.class).findProductJsonContent(productId, bestMatchVersion)).withSelfRel(); - model.setMetaProductJsonUrl(link.getHref()); - } - } catch (JsonProcessingException jsonProcessingException) { - log.error(jsonProcessingException.getMessage()); - } model.add(linkTo(selfLinkWithTag).withSelfRel()); createDetailResource(model, product); diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java index 1170235a4..fa5504c3a 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java @@ -101,7 +101,7 @@ public ResponseEntity> findProductVersionsById( @GetMapping(PRODUCT_JSON_CONTENT_BY_PRODUCT_ID_AND_VERSION) @Operation(summary = "Get product json content for designer to install", description = "When we click install in designer, this API will send content of product json for installing in Ivy designer") public ResponseEntity> findProductJsonContent(@PathVariable(PRODUCT_ID) String productId, - @PathVariable(VERSION) String version) throws JsonProcessingException { + @PathVariable(VERSION) String version) { Map productJsonContent = versionService.getProductJsonContentByIdAndVersion(productId, version); return new ResponseEntity<>(productJsonContent, HttpStatus.OK); } diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/VersionAndUrlModel.java b/marketplace-service/src/main/java/com/axonivy/market/model/VersionAndUrlModel.java index 2728a801a..a43938300 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/VersionAndUrlModel.java +++ b/marketplace-service/src/main/java/com/axonivy/market/model/VersionAndUrlModel.java @@ -1,6 +1,7 @@ package com.axonivy.market.model; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -9,6 +10,7 @@ @Setter @AllArgsConstructor @NoArgsConstructor +@Builder public class VersionAndUrlModel { String version; String url; diff --git a/marketplace-service/src/main/java/com/axonivy/market/service/VersionService.java b/marketplace-service/src/main/java/com/axonivy/market/service/VersionService.java index 64f3faddf..759df7641 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/service/VersionService.java +++ b/marketplace-service/src/main/java/com/axonivy/market/service/VersionService.java @@ -15,8 +15,7 @@ public interface VersionService { List getArtifactsAndVersionToDisplay(String productId, Boolean isShowDevVersion, String designerVersion); - Map getProductJsonContentByIdAndVersion(String name , String version) - throws JsonProcessingException; + Map getProductJsonContentByIdAndVersion(String name , String version); List getVersionsForDesigner(String productId) throws JsonProcessingException; } \ No newline at end of file diff --git a/marketplace-service/src/main/java/com/axonivy/market/service/impl/VersionServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/service/impl/VersionServiceImpl.java index ec97d32ac..bc51c2417 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/service/impl/VersionServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/service/impl/VersionServiceImpl.java @@ -113,14 +113,19 @@ public List getArtifactsAndVersionToDisplay(String pr } @Override - public Map getProductJsonContentByIdAndVersion(String productId, String version) - throws JsonProcessingException { - ProductJsonContent productJsonContent = productJsonContentRepository.findByProductIdAndVersion(productId, version); - if (ObjectUtils.isEmpty(productJsonContent)) { - return new HashMap<>(); + public Map getProductJsonContentByIdAndVersion(String productId, String version){ + Map result = new HashMap<>(); + try { + ProductJsonContent productJsonContent = productJsonContentRepository.findByProductIdAndVersion(productId, version); + if (ObjectUtils.isEmpty(productJsonContent)) { + return new HashMap<>(); + } + result = mapper.readValue(productJsonContent.getContent(), Map.class); + result.computeIfAbsent(NAME, k -> productJsonContent.getName()); + + } catch (JsonProcessingException jsonProcessingException){ + log.error(jsonProcessingException.getMessage()); } - Map result = mapper.readValue(productJsonContent.getContent(), Map.class); - result.computeIfAbsent(NAME, k -> productJsonContent.getName()); return result; } diff --git a/marketplace-service/src/test/java/com/axonivy/market/assembler/ProductDetailModelAssemblerTest.java b/marketplace-service/src/test/java/com/axonivy/market/assembler/ProductDetailModelAssemblerTest.java index cf350ae1e..5f83d10bc 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/assembler/ProductDetailModelAssemblerTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/assembler/ProductDetailModelAssemblerTest.java @@ -10,6 +10,8 @@ import org.mockito.InjectMocks; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.List; + @ExtendWith(MockitoExtension.class) class ProductDetailModelAssemblerTest { private static final String ID = "portal"; @@ -25,6 +27,7 @@ void setup() { productDetailModelAssembler = new ProductDetailModelAssembler(new ProductModelAssembler()); mockProduct = new Product(); mockProduct.setId(ID); + mockProduct.setReleasedVersions(List.of("11.0.1", "10.0.8")); } @Test @@ -47,9 +50,10 @@ void testToModelWithRequestPathAndVersion() { Assertions.assertTrue(model.getLink(SELF_RELATION).get().getHref().endsWith("/api/product-details/portal/10.0.19")); } -// @Test -// void testToModelWithRequestPathAndBestMatchVersion() { -// ProductDetailModel model = productDetailModelAssembler.toModel(mockProduct, VERSION, RequestMappingConstants.BEST_MATCH_BY_ID_AND_VERSION); -// Assertions.assertTrue(model.getLink(SELF_RELATION).get().getHref().endsWith("/api/product-details/portal/10.0.19/bestmatch")); -// } + @Test + void testToModelWithRequestPathAndBestMatchVersion() { + ProductDetailModel model = productDetailModelAssembler.toModel(mockProduct, VERSION, RequestMappingConstants.BEST_MATCH_BY_ID_AND_VERSION); + Assertions.assertEquals(model.getMetaProductJsonUrl(), "/api/product-details/productjsoncontent/portal/10.0.8"); + Assertions.assertTrue(model.getLink(SELF_RELATION).get().getHref().endsWith("/api/product-details/portal/10.0.19/bestmatch")); + } } \ No newline at end of file diff --git a/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java b/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java index 36ffbf4de..9e0b8b5a8 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java @@ -13,6 +13,8 @@ import java.util.Map; import com.axonivy.market.constants.RequestMappingConstants; import com.axonivy.market.entity.productjsonfilecontent.ProductJsonContent; +import com.axonivy.market.model.VersionAndUrlModel; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -122,18 +124,34 @@ void testSyncInstallationCount() { assertEquals(1, result.getBody()); } -// @Test -// void findProductVersionsById() { -// when(versionService.getVersionsForDesigner("google-maps-connector")).thenReturn( -// List.of("10.0.21", "10.0.22", "10.0.23")); -// -// var result = productDetailsController.findVersionsForDesigner("google-maps-connector"); -// -// assertEquals(3, Objects.requireNonNull(result.getBody()).size()); -// assertEquals("10.0.21", Objects.requireNonNull(result.getBody()).get(0)); -// assertEquals("10.0.22", Objects.requireNonNull(result.getBody()).get(1)); -// assertEquals("10.0.23", Objects.requireNonNull(result.getBody()).get(2)); -// } + @Test + void findProductVersionsById() throws JsonProcessingException { + when(versionService.getVersionsForDesigner("google-maps-connector")).thenReturn(mockVersionAndUrlModels()); + + var result = productDetailsController.findVersionsForDesigner("google-maps-connector"); + + assertEquals(2, Objects.requireNonNull(result.getBody()).size()); + assertEquals("10.0.21", Objects.requireNonNull(result.getBody()).get(0).getVersion()); + assertEquals("/api/product-details/productjsoncontent/portal/10.0.21", + Objects.requireNonNull(result.getBody()).get(0).getUrl()); + assertEquals("10.0.22", Objects.requireNonNull(result.getBody()).get(1).getVersion()); + assertEquals("/api/product-details/productjsoncontent/portal/10.0.22", + Objects.requireNonNull(result.getBody()).get(1).getUrl()); + } + + private List mockVersionAndUrlModels(){ + VersionAndUrlModel versionAndUrlModel = VersionAndUrlModel.builder() + .version("10.0.21") + .url("/api/product-details/productjsoncontent/portal/10.0.21") + .build(); + + VersionAndUrlModel versionAndUrlModel2 = VersionAndUrlModel.builder() + .version("10.0.22") + .url("/api/product-details/productjsoncontent/portal/10.0.22") + .build(); + + return List.of(versionAndUrlModel,versionAndUrlModel2); + } @Test void findProductJsonContentByIdAndTag() throws IOException { diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/impl/VersionServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/impl/VersionServiceImplTest.java index fad190518..aee74a98d 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/impl/VersionServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/impl/VersionServiceImplTest.java @@ -9,6 +9,7 @@ import com.axonivy.market.github.model.MavenArtifact; import com.axonivy.market.github.service.GHAxonIvyProductRepoService; import com.axonivy.market.model.MavenArtifactVersionModel; +import com.axonivy.market.model.VersionAndUrlModel; import com.axonivy.market.repository.MavenArtifactVersionRepository; import com.axonivy.market.repository.ProductJsonContentRepository; import com.axonivy.market.repository.ProductRepository; @@ -36,6 +37,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; @@ -417,15 +419,21 @@ void testGetRepoNameFromMarketRepo() { Assertions.assertEquals(expectedRepoName, result); } -// @Test -// void testGetVersionsForDesigner() { -// Mockito.when(productRepository.getReleasedVersionsById(anyString())) -// .thenReturn(List.of("11.3.0", "11.1.1", "11.1.0", "10.0.2")); -// -// List result = versionService.getVersionsForDesigner("11.3.0"); -// -// Assertions.assertEquals(result, List.of("11.3.0", "11.1.1", "11.1.0", "10.0.2")); -// } + @Test + void testGetVersionsForDesigner() throws JsonProcessingException { + Mockito.when(productRepository.getReleasedVersionsById(anyString())) + .thenReturn(List.of("11.3.0", "11.1.1", "11.1.0", "10.0.2")); + + List result = versionService.getVersionsForDesigner("11.3.0"); + + Assertions.assertEquals(result.stream().map(VersionAndUrlModel::getVersion).collect(Collectors.toList()), + List.of("11.3.0", "11.1.1", "11.1.0", "10.0.2")); + Assertions.assertEquals("/api/product-details/productjsoncontent/11.3.0/11.3.0", result.get(0).getUrl()); + Assertions.assertEquals("/api/product-details/productjsoncontent/11.3.0/11.1.1", result.get(1).getUrl()); + Assertions.assertEquals("/api/product-details/productjsoncontent/11.3.0/11.1.0", result.get(2).getUrl()); + Assertions.assertEquals("/api/product-details/productjsoncontent/11.3.0/10.0.2", result.get(3).getUrl()); + + } @Test void testGetProductJsonContentByIdAndVersion() throws JsonProcessingException { diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.html b/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.html index e199644ae..60fb2a8c7 100644 --- a/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.html +++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.html @@ -7,7 +7,7 @@ buttonClass="form-select form-select-sm versions-selector__dropdown border__dropdown h-100 text-primary install-designer-dropdown" ariaLabel=".form-select-sm example" class="flex-grow-1 col-8" - [meta_data_json_url] = "meta_data_json_url()" + [metaDataJsonUrl] = "metaDataJsonUrl()" (itemSelected)="onSelectVersionInDesigner($event.value)"> @@ -18,7 +18,7 @@ onClick="function installInDesigner() { const selectedItemElement = document.querySelector('.install-designer-dropdown'); if (selectedItemElement) { - const metaDataJsonUrl = selectedItemElement.getAttribute('meta_data_json_url'); + const metaDataJsonUrl = selectedItemElement.getAttribute('metaDataJsonUrl'); console.log(metaDataJsonUrl); install(metaDataJsonUrl); } diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.ts b/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.ts index acc101330..d58252a46 100644 --- a/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.ts +++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.ts @@ -45,7 +45,7 @@ export class ProductDetailVersionActionComponent implements AfterViewInit { label: version, })); }); - meta_data_json_url = model(''); + metaDataJsonUrl = model(''); versionDropdownInDesigner: ItemDropdown[] = []; artifacts: WritableSignal = signal([]); @@ -156,7 +156,7 @@ export class ProductDetailVersionActionComponent implements AfterViewInit { const versionMap = data.map(data => data.version).map(version => 'Version '.concat(version)); data.forEach(data => { const currentVersion = 'Version '.concat(data.version); - const versionAndUrl: ItemDropdown = { value: currentVersion, label: currentVersion, meta_data_json_url: data.url }; + const versionAndUrl: ItemDropdown = { value: currentVersion, label: currentVersion, metaDataJsonUrl: data.url }; this.versionDropdownInDesigner.push(versionAndUrl); }); this.versions.set(versionMap); diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.html b/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.html index afc89ac76..8c523fef0 100644 --- a/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.html +++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.html @@ -70,7 +70,7 @@

class="w-100 d-flex d-lg-block text-end" (installationCount)="receiveInstallationCountData($event)" [(selectedVersion)]="selectedVersion!" - [(meta_data_json_url)]="metaProductJsonUrl!" + [(metaDataJsonUrl)]="metaProductJsonUrl!" [productId]="productDetail().id" [product]="productDetail()" (selectedVersionChange)=" diff --git a/marketplace-ui/src/app/shared/components/common-dropdown/common-dropdown.component.html b/marketplace-ui/src/app/shared/components/common-dropdown/common-dropdown.component.html index 53919e855..67c354a3f 100644 --- a/marketplace-ui/src/app/shared/components/common-dropdown/common-dropdown.component.html +++ b/marketplace-ui/src/app/shared/components/common-dropdown/common-dropdown.component.html @@ -2,14 +2,14 @@