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 b77181b8b..d17b93f4e 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
@@ -21,6 +21,7 @@ import { LanguageService } from '../../../../core/services/language/language.ser
import { ItemDropdown } from '../../../../shared/models/item-dropdown.model';
import { ProductDetail } from '../../../../shared/models/product-detail.model';
import { environment } from '../../../../../environments/environment';
+import { VERSION } from '../../../../shared/constants/common.constant';
@Component({
selector: 'app-product-version-action',
standalone: true,
@@ -166,7 +167,7 @@ export class ProductDetailVersionActionComponent implements AfterViewInit {
)
.subscribe(data => {
data.forEach(item => {
- const version = 'Version '.concat(item.version);
+ const version = VERSION.displayPrefix.concat(item.version);
this.versions.update(currentVersions => [
...currentVersions,
version
@@ -187,7 +188,7 @@ export class ProductDetailVersionActionComponent implements AfterViewInit {
if (this.versions().length === 0) {
this.productService.sendRequestToGetProductVersionsForDesigner(this.productId
).subscribe(data => {
- const versionMap = data.map((versionNumber: string) => 'Version '.concat(versionNumber));
+ const versionMap = data.map((versionNumber: string) => VERSION.displayPrefix.concat(versionNumber));
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 99dd292cd..898a4f1e6 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
@@ -58,7 +58,7 @@
- {{ productDetail().type }}
+ {{ productDetail().type | productType | translate }}
@@ -116,7 +116,7 @@
-
-
-
-
-
-
-
-
-
-
-
+ @if (!isEmptyProductContent()) {
+
+
+
+
+
+
+
+
+
+
+ }
diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.spec.ts b/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.spec.ts
index fbe69c34e..5a6199ffa 100644
--- a/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.spec.ts
+++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.spec.ts
@@ -140,7 +140,7 @@ describe('ProductDetailComponent', () => {
});
it('should call setActiveTab and updateDropdownSelection on onTabChange', () => {
- const event ={ value: 'description' };
+ const event = { value: 'description' };
spyOn(component, 'setActiveTab');
spyOn(component, 'updateDropdownSelection');
@@ -159,6 +159,15 @@ describe('ProductDetailComponent', () => {
expect(component.getContent('description')).toBeTrue();
});
+ it('should return false in tab visibility when product module content is missing', () => {
+ const mockEmptyContent: ProductModuleContent = {} as ProductModuleContent;
+ component.productModuleContent.set(mockEmptyContent);
+ expect(component.getContent('description')).toBeFalse();
+ expect(component.getContent('demo')).toBeFalse();
+ expect(component.getContent('setup')).toBeFalse();
+ expect(component.getContent('dependency')).toBeFalse();
+ });
+
it('should return false for description when it is null or empty', () => {
const mockContentWithEmptyDescription: ProductModuleContent =
MOCK_PRODUCT_MODULE_CONTENT;
@@ -195,6 +204,16 @@ describe('ProductDetailComponent', () => {
expect(component.getContent('setup')).toBeFalse();
});
+ it('should not display information when product detail is empty', () => {
+ const mockContentWithEmptySetup: ProductModuleContent =
+ {} as ProductModuleContent;
+ component.productModuleContent.set(mockContentWithEmptySetup);
+ expect(component.isEmptyProductContent()).toBeTrue();
+ fixture.detectChanges();
+ const description = fixture.debugElement.query(By.css('#description'));
+ expect(description).toBeFalsy();
+ });
+
it('should display dropdown horizontally on small viewport', () => {
viewport.set(540);
const tabGroup = fixture.debugElement.query(By.css('.row-tab'));
@@ -297,4 +316,22 @@ describe('ProductDetailComponent', () => {
component.onResize();
expect(component.checkMediaSize).toHaveBeenCalled();
});
+
+ it('should be empty selected version if product detail content is missing', () => {
+ component.productModuleContent.set({} as ProductModuleContent);
+ component.selectedVersion = '';
+ component.handleProductContentVersion();
+ expect(component.selectedVersion).toEqual('');
+ });
+
+ it('should be formated selected version if open in designer', () => {
+ const mockContent: ProductModuleContent = {
+ ...MOCK_PRODUCT_MODULE_CONTENT,
+ tag: '10.0.11'
+ };
+ component.productModuleContent.set(mockContent);
+ routingQueryParamService.isDesignerEnv.and.returnValue(true);
+ component.handleProductContentVersion();
+ expect(component.selectedVersion).toEqual('Version 10.0.11');
+ });
});
diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.ts b/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.ts
index 20a79379e..232d12d5f 100644
--- a/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.ts
+++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail.component.ts
@@ -17,7 +17,10 @@ import { CommonModule } from '@angular/common';
import { ProductDetailInformationTabComponent } from './product-detail-information-tab/product-detail-information-tab.component';
import { ProductDetailVersionActionComponent } from './product-detail-version-action/product-detail-version-action.component';
import { ProductDetailMavenContentComponent } from './product-detail-maven-content/product-detail-maven-content.component';
-import { PRODUCT_DETAIL_TABS } from '../../../shared/constants/common.constant';
+import {
+ PRODUCT_DETAIL_TABS,
+ VERSION
+} from '../../../shared/constants/common.constant';
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
import { LanguageService } from '../../../core/services/language/language.service';
import { MultilingualismPipe } from '../../../shared/pipes/multilingualism.pipe';
@@ -35,6 +38,7 @@ import { RoutingQueryParamService } from '../../../shared/services/routing.query
import { CommonDropdownComponent } from '../../../shared/components/common-dropdown/common-dropdown.component';
import { CommonUtils } from '../../../shared/utils/common.utils';
import { ItemDropdown } from '../../../shared/models/item-dropdown.model';
+import { ProductTypePipe } from '../../../shared/pipes/product-type.pipe';
export interface DetailTab {
activeClass: string;
@@ -58,6 +62,7 @@ const DEFAULT_ACTIVE_TAB = 'description';
ProductDetailMavenContentComponent,
NgbNavModule,
MultilingualismPipe,
+ ProductTypePipe,
ProductDetailFeedbackComponent,
ProductInstallationCountActionComponent,
ProductTypeIconPipe,
@@ -107,7 +112,6 @@ export class ProductDetailComponent {
this.updateDropdownSelection();
}
-
constructor() {
this.scrollToTop();
this.resizeObserver = new ResizeObserver(() => {
@@ -122,17 +126,11 @@ export class ProductDetailComponent {
this.getProductById(productId).subscribe(productDetail => {
this.productDetail.set(productDetail);
this.productModuleContent.set(productDetail.productModuleContent);
- if (this.routingQueryParamService.isDesignerEnv()) {
- this.selectedVersion = 'Version '.concat(this.convertTagToVersion((productDetail.productModuleContent.tag)));
- }
this.detailTabsForDropdown = this.getNotEmptyTabs();
this.productDetailService.productNames.set(productDetail.names);
localStorage.removeItem(STORAGE_ITEM);
this.installationCount = productDetail.installationCount;
- this.selectedVersion = this.productModuleContent().tag;
- if (this.selectedVersion.startsWith('v')) {
- this.selectedVersion = this.selectedVersion.substring(1);
- }
+ this.handleProductContentVersion();
});
this.productFeedbackService.initFeedbacks();
this.productStarRatingService.fetchData();
@@ -145,6 +143,18 @@ export class ProductDetailComponent {
this.updateDropdownSelection();
}
+ handleProductContentVersion() {
+ if (this.isEmptyProductContent()) {
+ return;
+ }
+ this.selectedVersion = this.convertTagToVersion(
+ this.productModuleContent().tag
+ );
+ if (this.routingQueryParamService.isDesignerEnv()) {
+ this.selectedVersion = VERSION.displayPrefix.concat(this.selectedVersion);
+ }
+ }
+
scrollToTop() {
window.scrollTo({ left: 0, top: 0, behavior: 'instant' });
}
@@ -177,20 +187,28 @@ export class ProductDetailComponent {
}
getContent(value: string): boolean {
+ if (this.isEmptyProductContent()) {
+ return false;
+ }
const content = this.productModuleContent();
const conditions: { [key: string]: boolean } = {
description: content.description !== null,
demo: content.demo !== null,
- setup: content.setup !== null ,
+ setup: content.setup !== null,
dependency: content.isDependency
};
return conditions[value] ?? false;
}
+ isEmptyProductContent(): boolean {
+ const content = this.productModuleContent();
+ return !content || Object.keys(content).length === 0;
+ }
+
loadDetailTabs(selectedVersion: string) {
let version = selectedVersion || this.productDetail().newestReleaseVersion;
- version = version.replace("Version ","")
+ version = version.replace(VERSION.displayPrefix, '');
this.productService
.getProductDetailsWithVersion(this.productDetail().id, version)
.subscribe(updatedProductDetail => {
@@ -240,10 +258,11 @@ export class ProductDetailComponent {
@HostListener('document:click', ['$event'])
handleClickOutside(event: MouseEvent) {
+ const formSelect =
+ this.elementRef.nativeElement.querySelector('.form-select');
if (
- !this.elementRef.nativeElement
- .querySelector('.form-select')
- .contains(event.target) &&
+ formSelect &&
+ !formSelect.contains(event.target) &&
this.isTabDropdownShown()
) {
this.onTabDropdownShown();
@@ -288,8 +307,8 @@ export class ProductDetailComponent {
return this.detailTabsForDropdown.filter(tab => this.getContent(tab.value));
}
- convertTagToVersion(tag: string) : string {
- if (tag !== '' && tag.startsWith('v')){
+ convertTagToVersion(tag: string): string {
+ if (tag !== '' && tag.startsWith(VERSION.tagPrefix)) {
return tag.substring(1);
}
return tag;
diff --git a/marketplace-ui/src/app/modules/product/product-filter/product-filter.component.html b/marketplace-ui/src/app/modules/product/product-filter/product-filter.component.html
index 5338fb5ae..bc9125742 100644
--- a/marketplace-ui/src/app/modules/product/product-filter/product-filter.component.html
+++ b/marketplace-ui/src/app/modules/product/product-filter/product-filter.component.html
@@ -10,9 +10,9 @@
'border-light text-light': themeService.isDarkMode(),
'border-dark text-dark': !themeService.isDarkMode(),
'bg-light text-dark':
- selectedTypeLabel === type.value && themeService.isDarkMode(),
+ selectedTypeLabel === type.label && themeService.isDarkMode(),
'bg-primary border-0 text-light':
- selectedTypeLabel === type.value && !themeService.isDarkMode()
+ selectedTypeLabel === type.label && !themeService.isDarkMode()
}">
{{ type.label | translate }}
diff --git a/marketplace-ui/src/app/shared/constants/common.constant.ts b/marketplace-ui/src/app/shared/constants/common.constant.ts
index 507ddba08..c37d19e69 100644
--- a/marketplace-ui/src/app/shared/constants/common.constant.ts
+++ b/marketplace-ui/src/app/shared/constants/common.constant.ts
@@ -190,3 +190,8 @@ export const DEFAULT_PAGEABLE_IN_REST_CLIENT: Pageable = {
page: 0,
size: 40
};
+
+export const VERSION = {
+ tagPrefix: 'v',
+ displayPrefix: 'Version '
+};
diff --git a/marketplace-ui/src/app/shared/pipes/product-type.pipe.ts b/marketplace-ui/src/app/shared/pipes/product-type.pipe.ts
new file mode 100644
index 000000000..7c922ba25
--- /dev/null
+++ b/marketplace-ui/src/app/shared/pipes/product-type.pipe.ts
@@ -0,0 +1,11 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ standalone: true,
+ name: 'productType'
+})
+export class ProductTypePipe implements PipeTransform {
+ transform(type: string, _args?: []): string {
+ return `common.filter.value.${type}`;
+ }
+}
diff --git a/marketplace-ui/src/assets/i18n/de.yaml b/marketplace-ui/src/assets/i18n/de.yaml
index 2fd8fd53e..847497ad7 100644
--- a/marketplace-ui/src/assets/i18n/de.yaml
+++ b/marketplace-ui/src/assets/i18n/de.yaml
@@ -19,8 +19,8 @@ common:
label: Filter
value:
allTypes: Alle
- connector: Konnektoren
- util: Utilities
+ connector: Konnektor
+ util: Nützliches
demos: Demos
solution: Lösungen
sort:
@@ -97,9 +97,9 @@ common:
loggedGithubAsLabel: Eingeloggt bei Github als
reviewLabel: Überprüfung
detailedReviews: Ausführliche Bewertungen
- rateLinkLabel: Diesen Stecker bewerten
+ rateLinkLabel: Bewerte diesen Konnektor
showMoreBtnLabel: Mehr anzeigen
- noFeedbackMessage1: Es gibt noch keine Rückmeldungen für diesen Anschluss.
- noFeedbackMessage2: Seien Sie der Erste, der seine Meinung mitteilt.
- rateFeedbackBtnLabel: Diesen Stecker bewerten
- reviewLabelNoYet: Noch keine Bewertungen
+ noFeedbackMessage1: Deine Meinung ist gefragt.
+ noFeedbackMessage2: ''
+ rateFeedbackBtnLabel: Bewerte diesen Konnektor
+ reviewLabelNoYet: Noch keine Bewertungen
\ No newline at end of file