Skip to content

Commit

Permalink
Handle feedbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
nntthuy-axonivy committed Aug 1, 2024
1 parent 8abef23 commit bed1afb
Show file tree
Hide file tree
Showing 13 changed files with 106 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class RequestParamConstants {
public static final String TYPE = "type";
public static final String KEYWORD = "keyword";
public static final String LANGUAGE = "language";
public static final String IS_REST_DESIGNER = "isRestDesigner";
public static final String IS_REST_CLIENT = "isRESTClient";
public static final String USER_ID = "userId";
public static final String AUTHORIZATION = "Authorization";
public static final String X_AUTHORIZATION = "X-Authorization";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
import static com.axonivy.market.constants.RequestParamConstants.LANGUAGE;
import static com.axonivy.market.constants.RequestParamConstants.RESET_SYNC;
import static com.axonivy.market.constants.RequestParamConstants.TYPE;
import static com.axonivy.market.constants.RequestParamConstants.IS_REST_DESIGNER;
import static com.axonivy.market.constants.RequestParamConstants.IS_REST_CLIENT;

@RestController
@RequestMapping(PRODUCT)
Expand Down Expand Up @@ -73,9 +73,9 @@ public ResponseEntity<PagedModel<ProductModel>> findProducts(
@RequestParam(name = TYPE) @Parameter(description = "Type of product.", in = ParameterIn.QUERY, schema = @Schema(type = "string", allowableValues = {"all", "connectors", "utilities", "solutions", "demos"})) String type,
@RequestParam(required = false, name = KEYWORD) @Parameter(description = "Keyword that exist in product's name or short description", example = "connector", in = ParameterIn.QUERY) String keyword,
@RequestParam(name = LANGUAGE) @Parameter(description = "Language of product short description", in = ParameterIn.QUERY, schema = @Schema(allowableValues = {"en", "de"})) String language,
@RequestParam(name = IS_REST_DESIGNER) @Parameter(description = "Option to get REST client environment", in = ParameterIn.QUERY) Boolean isRestDesigner,
@RequestParam(name = IS_REST_CLIENT) @Parameter(description = "Option to render the website in the REST Client Editor of Designer", in = ParameterIn.QUERY) Boolean isRESTClient,
@ParameterObject Pageable pageable) {
Page<Product> results = productService.findProducts(type, keyword, language, isRestDesigner, pageable);
Page<Product> results = productService.findProducts(type, keyword, language, isRESTClient, pageable);
if (results.isEmpty()) {
return generateEmptyPagedModel();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import org.springframework.data.domain.Pageable;

public interface ProductService {
Page<Product> findProducts(String type, String keyword, String language, Boolean isRestDesigner, Pageable pageable);
Page<Product> findProducts(String type, String keyword, String language, Boolean isRESTClient, Pageable pageable);

boolean syncLatestDataFromMarketRepo();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.axonivy.market.service.impl;

import static com.axonivy.market.enums.DocumentField.MARKET_DIRECTORY;
import static com.axonivy.market.enums.DocumentField.SHORT_DESCRIPTIONS;

import static java.util.Optional.ofNullable;
import static org.apache.commons.lang3.StringUtils.EMPTY;

Expand All @@ -14,7 +16,6 @@
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;

Expand Down Expand Up @@ -105,16 +106,15 @@ public ProductServiceImpl(ProductRepository productRepository, GHAxonIvyMarketRe
}

@Override
public Page<Product> findProducts(String type, String keyword, String language, Boolean isRestDesigner,
public Page<Product> findProducts(String type, String keyword, String language, Boolean isRESTClient,
Pageable pageable) {
final var typeOption = TypeOption.of(type);
final var searchPageable = refinePagination(language, pageable);
var searchCriteria = new ProductSearchCriteria();
searchCriteria.setListed(true);
searchCriteria.setKeyword(keyword);
if (BooleanUtils.isTrue(isRestDesigner)) {
searchCriteria.setType(TypeOption.CONNECTORS);
searchCriteria.setLanguage(Language.of(Locale.ENGLISH.toLanguageTag()));
if (BooleanUtils.isTrue(isRESTClient)) {
searchCriteria.setExcludeFields(List.of(SHORT_DESCRIPTIONS));
} else {
searchCriteria.setType(typeOption);
searchCriteria.setLanguage(Language.of(language));
Expand Down Expand Up @@ -223,37 +223,37 @@ private void updateLatestChangeToProductsFromGithubRepo() {
private void modifyProductLogo(String parentPath, GitHubFile file, Product product, GHContent fileContent) {
Product result;
switch (file.getStatus()) {
case MODIFIED, ADDED:
var searchCriteria = new ProductSearchCriteria();
searchCriteria.setKeyword(parentPath);
searchCriteria.setFields(List.of(MARKET_DIRECTORY));
result = productRepository.findByCriteria(searchCriteria);
if (result != null) {
result.setLogoUrl(GitHubUtils.getDownloadUrl(fileContent));
productRepository.save(result);
}
break;
case REMOVED:
result = productRepository.findByLogoUrl(product.getLogoUrl());
if (result != null) {
productRepository.deleteById(result.getId());
}
break;
default:
break;
case MODIFIED, ADDED:
var searchCriteria = new ProductSearchCriteria();
searchCriteria.setKeyword(parentPath);
searchCriteria.setFields(List.of(MARKET_DIRECTORY));
result = productRepository.findByCriteria(searchCriteria);
if (result != null) {
result.setLogoUrl(GitHubUtils.getDownloadUrl(fileContent));
productRepository.save(result);
}
break;
case REMOVED:
result = productRepository.findByLogoUrl(product.getLogoUrl());
if (result != null) {
productRepository.deleteById(result.getId());
}
break;
default:
break;
}
}

private void modifyProductByMetaContent(GitHubFile file, Product product) {
switch (file.getStatus()) {
case MODIFIED, ADDED:
productRepository.save(product);
break;
case REMOVED:
productRepository.deleteById(product.getId());
break;
default:
break;
case MODIFIED, ADDED:
productRepository.save(product);
break;
case REMOVED:
productRepository.deleteById(product.getId());
break;
default:
break;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import static com.axonivy.market.constants.CommonConstants.LOGO_FILE;
import static com.axonivy.market.constants.CommonConstants.SLASH;
import static com.axonivy.market.constants.MetaConstants.META_FILE;
import static com.axonivy.market.enums.DocumentField.SHORT_DESCRIPTIONS;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
Expand Down Expand Up @@ -31,6 +33,7 @@
import java.util.UUID;
import java.util.stream.Collectors;

import com.axonivy.market.criteria.ProductSearchCriteria;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand Down Expand Up @@ -120,6 +123,9 @@ class ProductServiceImplTest extends BaseSetup {
@Captor
ArgumentCaptor<ArrayList<Product>> productListArgumentCaptor;

@Captor
ArgumentCaptor<ProductSearchCriteria> productSearchCriteriaArgumentCaptor;

@InjectMocks
private ProductServiceImpl productService;

Expand Down Expand Up @@ -183,7 +189,7 @@ void testFindProducts() {

// Start testing by Connector
// Executes
result = productService.findProducts(TypeOption.CONNECTORS.getOption(), keyword, language, true, PAGEABLE);
result = productService.findProducts(TypeOption.CONNECTORS.getOption(), keyword, language, false, PAGEABLE);
assertEquals(mockResultReturn, result);

// Start testing by Other
Expand All @@ -192,6 +198,13 @@ void testFindProducts() {
assertEquals(2, result.getSize());
}

@Test
void testFindProductsInRESTClientOfDesigner() {
productService.findProducts(TypeOption.CONNECTORS.getOption(), keyword, Language.EN.getValue(), true, PAGEABLE);
verify(productRepository).searchByCriteria(productSearchCriteriaArgumentCaptor.capture(), any(Pageable.class));
assertEquals(List.of(SHORT_DESCRIPTIONS), productSearchCriteriaArgumentCaptor.getValue().getExcludeFields());
}

@Test
void testSyncProductsAsUpdateMetaJSONFromGitHub() throws IOException {
// Start testing by adding new meta
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
<div
class="card product-card w-100"
[style.height]="!isProductInRestClient ? '250px' : '164px'">
[style.height]="!isShowInRESTClientEditor ? '250px' : '164px'">
<div class="d-flex justify-content-between align-items-start">
<img
class="card-img-top rounded"
width="70"
height="70"
[ngSrc]="product | logo"
[alt]="
product.names | multilingualism: languageService.selectedLanguage()
" />

@if (!isProductInRestClient) {
[alt]="product.names | multilingualism: languageService.selectedLanguage()" />
@if (isShowInRESTClientEditor) {
<div
class="card__tag lh-md px-2 py-1"
class="card__tag lh-md px-2 py-1 text-capitalize"
[ngClass]="themeService.isDarkMode() ? 'text-dark' : 'text-light'">
{{ 'common.filter.value.' + product.type | translate }}
{{ product.tags[0] }}
</div>
}
@if (isProductInRestClient) {
} @else {
<div
class="card__tag lh-md px-2 py-1 text-capitalize"
class="card__tag lh-md px-2 py-1"
[ngClass]="themeService.isDarkMode() ? 'text-dark' : 'text-light'">
{{ product.tags[0] }}
{{ 'common.filter.value.' + product.type | translate }}
</div>
}
</div>
<div>
<h5 class="card__title text-primary">
{{ product.names | multilingualism: languageService.selectedLanguage() }}
{{
product.names | multilingualism: languageService.selectedLanguage()
}}
</h5>
@if (!isProductInRestClient) {
@if (!isShowInRESTClientEditor) {
<p class="card__description text-secondary">
{{
product.shortDescriptions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import {
MOCK_EMPTY_DE_VALUES_AND_NO_LOGO_URL_PRODUCTS,
MOCK_PRODUCTS
} from '../../../shared/mocks/mock-data';
import { MOCK_EMPTY_DE_VALUES_AND_NO_LOGO_URL_PRODUCTS, MOCK_PRODUCTS } from '../../../shared/mocks/mock-data';
import { ProductCardComponent } from './product-card.component';
import { Product } from '../../../shared/models/product.model';
import { Language } from '../../../shared/enums/language.enum';
Expand All @@ -16,6 +13,7 @@ import {
} from '@angular/common/http';
import { ActivatedRoute } from '@angular/router';
import { of } from 'rxjs';
import { By } from '@angular/platform-browser';

const products = MOCK_PRODUCTS._embedded.products as Product[];
const noDeNameAndNoLogoUrlProducts =
Expand Down Expand Up @@ -69,4 +67,24 @@ describe('ProductCardComponent', () => {
'Amazon Comprehend is a AI service that uses machine learning to uncover information in unstructured data.'
);
});

it('should display product tag in REST client', () => {
component.isShowInRESTClientEditor = true;
fixture.detectChanges();

const tagElement = fixture.debugElement.query(By.css('.card__tag'));
expect(tagElement).toBeTruthy();
expect(tagElement.nativeElement.textContent).toContain('AI');
});

it('should display product type in marketplace website', () => {
component.isShowInRESTClientEditor = false;
fixture.detectChanges();

const tagElement = fixture.debugElement.query(By.css('.card__tag'));
expect(tagElement).toBeTruthy();
expect(tagElement.nativeElement.textContent).toContain(
'common.filter.value.connector'
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,14 @@ import { ProductComponent } from '../product.component';
@Component({
selector: 'app-product-card',
standalone: true,
imports: [
CommonModule,
ProductLogoPipe,
MultilingualismPipe,
TranslateModule,
NgOptimizedImage
],
imports: [CommonModule, ProductLogoPipe, MultilingualismPipe, TranslateModule, NgOptimizedImage],
templateUrl: './product-card.component.html',
styleUrl: './product-card.component.scss'
})
export class ProductCardComponent {
themeService = inject(ThemeService);
languageService = inject(LanguageService);

isProductInRestClient = inject(ProductComponent).isRestClient();
isShowInRESTClientEditor = inject(ProductComponent).isRestClient();

@Input() product!: Product;
}
6 changes: 4 additions & 2 deletions marketplace-ui/src/app/modules/product/product.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class ProductComponent implements AfterViewInit, OnDestroy {
criteria: Criteria = {
search: '',
type: TypeOption.All_TYPES,
isRestDesigner: false,
isRESTClientEditor: false,
sort: SortOption.STANDARD,
language: Language.EN
};
Expand Down Expand Up @@ -136,7 +136,9 @@ export class ProductComponent implements AfterViewInit, OnDestroy {
loadProductItems(shouldCleanData = false) {
this.criteria.language = this.languageService.selectedLanguage();
if (this.isRestClient()) {
this.criteria.isRestDesigner = true;
this.criteria.isRESTClientEditor = true;
this.criteria.language = Language.EN;
this.criteria.type = TypeOption.CONNECTORS;
}

this.subscriptions.push(
Expand Down
Loading

0 comments on commit bed1afb

Please sign in to comment.