Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/marp 760 open marketplace from within designer install item #117

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
cfae46c
MARP-760 add dropdown and apis
tvtphuc-axonivy Aug 21, 2024
61c154f
MARP-760 install item to designer
tvtphuc-axonivy Aug 22, 2024
9f3460b
MARP-760 Install items
tvtphuc-axonivy Aug 22, 2024
8ffd757
MARP-760 remove unused code
tvtphuc-axonivy Aug 23, 2024
97734dc
MARP-760 Handle Feedback
tvtphuc-axonivy Aug 23, 2024
1aca058
MARP-760 Update in UI
tvtphuc-axonivy Aug 23, 2024
4d92fb5
MARP-760 increate installation count
tvtphuc-axonivy Aug 23, 2024
e0e6641
MARP-760 update UI
tvtphuc-axonivy Aug 23, 2024
f7f39c8
MARP-760 Handle Feedback
tvtphuc-axonivy Aug 26, 2024
57ab931
MARP-760 Pretty print for json
tvtphuc-axonivy Aug 26, 2024
c38e01b
MARP-760 Revert size for btn
tvtphuc-axonivy Aug 26, 2024
8744fb4
MARP-760 Fix Sonar
tvtphuc-axonivy Aug 26, 2024
bcb2ff9
MARP-760 remove unsed codes
tvtphuc-axonivy Aug 26, 2024
bfb3e3d
MARP-760 Fix Sonar
tvtphuc-axonivy Aug 26, 2024
7517eb5
MARP-760 Handle Feedback
tvtphuc-axonivy Aug 27, 2024
9dcc2d2
MARP-760 Handle Feedback
tvtphuc-axonivy Aug 27, 2024
80f7c0d
MARP-760 Handle Feedback
tvtphuc-axonivy Aug 27, 2024
4350f9a
MARP-760 Handle feedback
tvtphuc-axonivy Aug 27, 2024
d56c1a4
MARP-760 Use Constant
tvtphuc-axonivy Aug 27, 2024
de77e07
MARP-760 Handle Sonar
tvtphuc-axonivy Aug 27, 2024
f2ba49b
MARP-760 Handle Feedback
tvtphuc-axonivy Aug 27, 2024
6ea2bcd
MARP-760 Handle Feedback
tvtphuc-axonivy Aug 27, 2024
a2215e7
MARP-760 Handle Sonar
tvtphuc-axonivy Aug 27, 2024
62a77b8
MARP-470 Hanle Sonar
tvtphuc-axonivy Aug 27, 2024
a3fc9e7
MARP-760 Handle Feedback
tvtphuc-axonivy Aug 27, 2024
0fbf01a
MARP-760 Handle Sonar
tvtphuc-axonivy Aug 27, 2024
ec6d76f
Merge branch 'develop' into feature/MARP-760-Open-Marketplace-from-wi…
tvtphuc-axonivy Aug 27, 2024
0e3eb63
MARP-760 Handle Feedback and put the log to debug
tvtphuc-axonivy Aug 28, 2024
ae3275b
MARP-760 Handle Feedback
tvtphuc-axonivy Aug 30, 2024
b170899
MARP-760 Handle Feedback
tvtphuc-axonivy Aug 30, 2024
96702c8
Merge branch 'develop' into feature/MARP-760-Open-Marketplace-from-wi…
tvtphuc-axonivy Aug 30, 2024
8012552
MARP-760 Handle Sonar
tvtphuc-axonivy Aug 30, 2024
2d08f4e
MARP-760 Update UT
tvtphuc-axonivy Aug 30, 2024
c9ea382
MARP-760 Handle Sonar
tvtphuc-axonivy Aug 30, 2024
3048987
MARP-760 Handle Sonar
tvtphuc-axonivy Aug 30, 2024
c834e0e
MARP-760 Handle Feedback
tvtphuc-axonivy Aug 30, 2024
26e43c7
MARP-760 Remove white space
tvtphuc-axonivy Aug 30, 2024
c689984
MARP-760 Fix Sonar
tvtphuc-axonivy Aug 30, 2024
e28dfd2
MARP-760 Handle Sonar
tvtphuc-axonivy Aug 30, 2024
10036cd
MARP-760 Handle Sonar
tvtphuc-axonivy Aug 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import com.axonivy.market.controller.ProductDetailsController;
import com.axonivy.market.entity.Product;
import com.axonivy.market.model.ProductDetailModel;
import com.axonivy.market.util.VersionUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
Expand All @@ -16,6 +19,7 @@
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;

@Component
@Log4j2
public class ProductDetailModelAssembler extends RepresentationModelAssemblerSupport<Product, ProductDetailModel> {

private final ProductModelAssembler productModelAssembler;
Expand Down Expand Up @@ -43,14 +47,22 @@ 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);
case RequestMappingConstants.BY_ID_AND_VERSION ->
methodOn(ProductDetailsController.class).findProductDetailsByVersion(productId, version);
default ->
methodOn(ProductDetailsController.class).findProductDetails(productId);
default -> methodOn(ProductDetailsController.class).findProductDetails(productId);
};

tvtphuc-axonivy marked this conversation as resolved.
Show resolved Hide resolved
model.add(linkTo(selfLinkWithTag).withSelfRel());
createDetailResource(model, product);
return model;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
import static com.axonivy.market.constants.RequestMappingConstants.BEST_MATCH_BY_ID_AND_VERSION;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.JsonProcessingException;

import com.axonivy.market.model.VersionAndUrlModel;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
Expand Down Expand Up @@ -99,15 +100,15 @@ public ResponseEntity<List<MavenArtifactVersionModel>> 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<Map<String, Object>> findProductJsonContent(@PathVariable(PRODUCT_ID) String productId,
@PathVariable(VERSION) String version) throws JsonProcessingException {
@PathVariable(VERSION) String version) {
Map<String, Object> productJsonContent = versionService.getProductJsonContentByIdAndVersion(productId, version);
return new ResponseEntity<>(productJsonContent, HttpStatus.OK);
}

@GetMapping(VERSIONS_IN_DESIGNER)
@Operation(summary = "Get the list of released version in product", description = "Collect the released versions in product for ivy designer")
public ResponseEntity<List<String>> findVersionsForDesigner(@PathVariable(ID) String id) {
List<String> versionList = versionService.getVersionsForDesigner(id);
public ResponseEntity<List<VersionAndUrlModel>> findVersionsForDesigner(@PathVariable(ID) String id) {
List<VersionAndUrlModel> versionList = versionService.getVersionsForDesigner(id);
return new ResponseEntity<>(versionList, HttpStatus.OK);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;

import java.io.Serial;
Expand Down Expand Up @@ -62,6 +63,9 @@ public class Product implements Serializable {
private Integer customOrder;
private List<String> releasedVersions;

@Transient
private String metaProductJsonUrl;

@Override
public int hashCode() {
return new HashCodeBuilder().append(id).hashCode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public class ProductDetailModel extends ProductModel {
private ProductModuleContent productModuleContent;
@Schema(description = "Installation/download count", example = "0")
private int installationCount;
@Schema(description = "The api url to get metadata from product.json")
private String metaProductJsonUrl;

@Override
public int hashCode() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.axonivy.market.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class VersionAndUrlModel {
String version;
String url;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.axonivy.market.service;

import com.axonivy.market.model.MavenArtifactVersionModel;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.axonivy.market.model.VersionAndUrlModel;
import java.util.List;
import java.util.Map;

Expand All @@ -14,8 +14,7 @@ public interface VersionService {
List<MavenArtifactVersionModel> getArtifactsAndVersionToDisplay(String productId, Boolean isShowDevVersion,
String designerVersion);

Map<String, Object> getProductJsonContentByIdAndVersion(String name , String version)
throws JsonProcessingException;
Map<String, Object> getProductJsonContentByIdAndVersion(String name , String version);

List<String> getVersionsForDesigner(String productId);
List<VersionAndUrlModel> getVersionsForDesigner(String productId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.axonivy.market.constants.CommonConstants;
import com.axonivy.market.constants.GitHubConstants;
import com.axonivy.market.constants.MavenConstants;
import com.axonivy.market.controller.ProductDetailsController;
import com.axonivy.market.entity.MavenArtifactModel;
import com.axonivy.market.entity.MavenArtifactVersion;
import com.axonivy.market.entity.Product;
Expand All @@ -16,6 +17,7 @@
import com.axonivy.market.github.service.GHAxonIvyProductRepoService;
import com.axonivy.market.github.util.GitHubUtils;
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;
Expand All @@ -29,6 +31,7 @@
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.kohsuke.github.GHContent;
import org.springframework.hateoas.Link;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

Expand All @@ -44,7 +47,8 @@
import java.util.Set;

import static com.axonivy.market.constants.ProductJsonConstants.NAME;

import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
@Log4j2
@Service
@Getter
Expand Down Expand Up @@ -109,20 +113,33 @@ public List<MavenArtifactVersionModel> getArtifactsAndVersionToDisplay(String pr
}

@Override
public Map<String, Object> getProductJsonContentByIdAndVersion(String productId, String version)
throws JsonProcessingException {
ProductJsonContent productJsonContent = productJsonContentRepository.findByProductIdAndVersion(productId, version);
if (ObjectUtils.isEmpty(productJsonContent)) {
return new HashMap<>();
public Map<String, Object> getProductJsonContentByIdAndVersion(String productId, String version){
Map<String, Object> 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<String, Object> result = mapper.readValue(productJsonContent.getContent(), Map.class);
result.computeIfAbsent(NAME, k -> productJsonContent.getName());
return result;
}

@Override
public List<String> getVersionsForDesigner(String productId) {
return productRepository.getReleasedVersionsById(productId);
public List<VersionAndUrlModel> getVersionsForDesigner(String productId) {
List<VersionAndUrlModel> versionAndUrlList = new ArrayList<>();
List<String> versions = productRepository.getReleasedVersionsById(productId);
for (String version : versions) {
Link link = linkTo(
methodOn(ProductDetailsController.class).findProductJsonContent(productId, version)).withSelfRel();
VersionAndUrlModel versionAndUrlModel = new VersionAndUrlModel(version, link.getHref());
versionAndUrlList.add(versionAndUrlModel);
}
return versionAndUrlList;
}

public boolean handleArtifactForVersionToDisplay(List<String> versionsToDisplay,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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
Expand All @@ -51,5 +54,6 @@ void testToModelWithRequestPathAndVersion() {
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"));
Assertions.assertTrue(model.getMetaProductJsonUrl().endsWith("/api/product-details/productjsoncontent/portal/10.0.8"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
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.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -124,15 +125,31 @@ void testSyncInstallationCount() {

@Test
void findProductVersionsById() {
when(versionService.getVersionsForDesigner("google-maps-connector")).thenReturn(
List.of("10.0.21", "10.0.22", "10.0.23"));
when(versionService.getVersionsForDesigner("google-maps-connector")).thenReturn(mockVersionAndUrlModels());

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));
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<VersionAndUrlModel> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
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;
import com.axonivy.market.util.XmlReaderUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.api.Fail;
import org.junit.jupiter.api.Assertions;
Expand All @@ -28,7 +28,6 @@
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -422,13 +421,19 @@ void testGetVersionsForDesigner() {
Mockito.when(productRepository.getReleasedVersionsById(anyString()))
.thenReturn(List.of("11.3.0", "11.1.1", "11.1.0", "10.0.2"));

List<String> result = versionService.getVersionsForDesigner("11.3.0");
List<VersionAndUrlModel> result = versionService.getVersionsForDesigner("11.3.0");

Assertions.assertEquals(result.stream().map(VersionAndUrlModel::getVersion).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());

Assertions.assertEquals(result, List.of("11.3.0", "11.1.1", "11.1.0", "10.0.2"));
}

@Test
void testGetProductJsonContentByIdAndVersion() throws JsonProcessingException {
void testGetProductJsonContentByIdAndVersion() {
ProductJsonContent mockProductJsonContent = new ProductJsonContent();
String mockContent = """
{
Expand Down Expand Up @@ -462,4 +467,13 @@ void testGetProductJsonContentByIdAndVersion() throws JsonProcessingException {

Assertions.assertEquals("Amazon Comprehend", result.get("name"));
}

@Test
void testGetProductJsonContentByIdAndVersion_noResult() {
Mockito.when(productJsonContentRepository.findByProductIdAndVersion(anyString(), anyString())).thenReturn(null);

Map<String, Object> result = versionService.getProductJsonContentByIdAndVersion("amazon-comprehend", "11.3.1");

Assertions.assertEquals(new HashMap<>(), result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,24 @@
<div class="designer-section d-flex justify-content-sm-between w-100 row">
<app-common-dropdown
(click)="getVersionInDesigner()"
[items]="versionDropdown()"
[items]="versionDropdownInDesigner"
[selectedItem]="selectedVersion()"
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"
[metaDataJsonUrl] = "metaDataJsonUrl()"
(itemSelected)="onSelectVersionInDesigner($event.value)">
</app-common-dropdown>

<button [lang]="languageService.selectedLanguage()"
class="btn btn__install flex-grow-1 install-designer-button m-0 col-4"
id="install-button"
[attr.product-id]="product.id"
[attr.request-path]="environment.apiUrl"
(click)="onUpdateInstallationCountForDesigner()"
onClick="function installInDesigner() {
const selectedItemElement = document.querySelector('.install-designer-dropdown');
if (selectedItemElement) {
const version = selectedItemElement.textContent.trim();
const productId = document.getElementById('install-button').getAttribute('product-id');
const requestPath = document.getElementById('install-button').getAttribute('request-path');
const url = `${requestPath}/api/product-details/productjsoncontent/${productId}/${version.replace('Version ','')}`
install(url);
const metaDataJsonUrl = selectedItemElement.getAttribute('metaDataJsonUrl');
install(metaDataJsonUrl);
}
}
installInDesigner();"
Expand Down
Loading
Loading