+
\ No newline at end of file
diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail-information-tab/product-detail-information-tab.component.ts b/marketplace-ui/src/app/modules/product/product-detail/product-detail-information-tab/product-detail-information-tab.component.ts
index 8c8ca8822..5d7bb86dc 100644
--- a/marketplace-ui/src/app/modules/product/product-detail/product-detail-information-tab/product-detail-information-tab.component.ts
+++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail-information-tab/product-detail-information-tab.component.ts
@@ -1,7 +1,8 @@
import { CommonModule } from '@angular/common';
-import { Component, Input } from '@angular/core';
+import { Component, inject, Input } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { ProductDetail } from '../../../../shared/models/product-detail.model';
+import { LanguageService } from '../../../../core/services/language/language.service';
@Component({
selector: 'app-product-detail-information-tab',
@@ -15,4 +16,6 @@ export class ProductDetailInformationTabComponent {
productDetail!: ProductDetail;
@Input()
selectedVersion!: string;
+
+ languageService = inject(LanguageService);
}
diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail-maven-content/product-detail-maven-content.component.html b/marketplace-ui/src/app/modules/product/product-detail/product-detail-maven-content/product-detail-maven-content.component.html
index ef973f8cf..15e185a93 100644
--- a/marketplace-ui/src/app/modules/product/product-detail/product-detail-maven-content/product-detail-maven-content.component.html
+++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail-maven-content/product-detail-maven-content.component.html
@@ -1,4 +1,4 @@
-
+
<!-- {{ productModuleContent.name }} -->
@@ -17,4 +17,4 @@
<type>{{ productModuleContent.type }}</type>
</dependency>
-
+
\ No newline at end of file
diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail-maven-content/product-detail-maven-content.component.ts b/marketplace-ui/src/app/modules/product/product-detail/product-detail-maven-content/product-detail-maven-content.component.ts
index 9d46efffb..a645e68e9 100644
--- a/marketplace-ui/src/app/modules/product/product-detail/product-detail-maven-content/product-detail-maven-content.component.ts
+++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail-maven-content/product-detail-maven-content.component.ts
@@ -1,6 +1,7 @@
-import { Component, Input } from '@angular/core';
+import { Component, inject, Input } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { ProductModuleContent } from '../../../../shared/models/product-module-content.model';
+import { LanguageService } from '../../../../core/services/language/language.service';
@Component({
selector: 'app-product-detail-maven-content',
@@ -14,4 +15,6 @@ export class ProductDetailMavenContentComponent {
productModuleContent!: ProductModuleContent;
@Input()
selectedVersion!: string;
+
+ languageService = inject(LanguageService);
}
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 5c1bffebf..ba3772e8c 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
@@ -1,11 +1,12 @@
-
-}
\ No newline at end of file
+}
diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.scss b/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.scss
index b4a900b92..e0c5fd357 100644
--- a/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.scss
+++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.scss
@@ -48,8 +48,15 @@
}
}
}
+::ng-deep .dropdown-menu {
+ min-width: 100%;
+}
+
+::ng-deep .dropdown-item {
+ font-size: 14px;
+}
-.fs-md {
+::ng-deep .fs-md {
font-size: 12px;
}
@@ -62,9 +69,11 @@
line-height: 14.52px;
text-align: left;
}
-.border__dropdown {
+
+::ng-deep .border__dropdown {
border: 0.5px solid var(--ivy-secondary-border-color);
}
+
.btn {
padding: 12px 32px;
gap: 10px;
@@ -85,7 +94,20 @@
color: var(--ivy-primary-bg);
}
-.dropdown-menu {
+::ng-deep .item-bar {
+ height: 44px;
+ padding: 15px;
+ gap: 10px;
+ font-size: 14px;
+ font-weight: 400;
+ line-height: 16.8px;
+}
+
+::ng-deep .dropdown-menu.menu-bar {
+ margin-top: 4px;
+}
+
+::ng-deep .dropdown-menu {
padding: 10px;
border-radius: 5px;
gap: 15px;
@@ -100,8 +122,10 @@
right: auto;
min-width: 80vw;
}
+
.form-group {
gap: 7px;
+
.form-select {
height: 32px;
padding: 9px 10px;
@@ -110,6 +134,7 @@
line-height: 12px;
text-align: start !important;
background-color: var(--ivy-text-normal-color);
+
option {
height: 44px;
padding: 15px;
diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.spec.ts b/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.spec.ts
index 67622107d..c96440d10 100644
--- a/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.spec.ts
+++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail-version-action/product-detail-version-action.component.spec.ts
@@ -4,8 +4,8 @@ import { ProductDetailVersionActionComponent } from './product-detail-version-ac
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { ProductService } from '../../product.service';
import { provideHttpClient } from '@angular/common/http';
-import { Artifact } from '../../../../shared/models/vesion-artifact.model';
import { ElementRef } from '@angular/core';
+import { ItemDropdown } from '../../../../shared/models/item-dropdown.model';
class MockElementRef implements ElementRef {
nativeElement = {
@@ -42,19 +42,18 @@ describe('ProductVersionActionComponent', () => {
});
it('first artifact should be chosen when select corresponding version', () => {
- component.onSelectVersion();
- expect(component.artifacts().length).toBe(0);
-
const selectedVersion = 'Version 10.0.2';
+ component.onSelectVersion(selectedVersion);
+ expect(component.artifacts().length).toBe(0);
const artifact = {
name: 'Example Artifact',
downloadUrl: 'https://example.com/download',
isProductArtifact: true
- } as Artifact;
+ } as ItemDropdown;
component.versions.set([selectedVersion]);
component.versionMap.set(selectedVersion, [artifact]);
component.selectedVersion.set(selectedVersion);
- component.onSelectVersion();
+ component.onSelectVersion(selectedVersion);
expect(component.artifacts().length).toBe(1);
expect(component.selectedArtifact).toEqual('https://example.com/download');
@@ -66,7 +65,7 @@ describe('ProductVersionActionComponent', () => {
name: 'Example Artifact',
downloadUrl: 'https://example.com/download',
isProductArtifact: true
- } as Artifact;
+ } as ItemDropdown;
component.selectedVersion.set(selectedVersion);
component.selectedArtifact = artifact.downloadUrl;
component.versions().push(selectedVersion);
@@ -76,7 +75,7 @@ describe('ProductVersionActionComponent', () => {
expect(component.artifacts().length).toBe(1);
expect(component.selectedVersion()).toBe(selectedVersion);
expect(component.selectedArtifact).toBe('https://example.com/download');
- component.sanitizeDataBeforFetching();
+ component.sanitizeDataBeforeFetching();
expect(component.versions().length).toBe(0);
expect(component.artifacts().length).toBe(0);
expect(component.selectedVersion()).toEqual('');
@@ -84,7 +83,7 @@ describe('ProductVersionActionComponent', () => {
});
it('should call sendRequestToProductDetailVersionAPI and update versions and versionMap', () => {
- const { mockArtifct1, mockArtifct2 } = mockApiWithExpectedResponse();
+ const { mockArtifact1, mockArtifact2 } = mockApiWithExpectedResponse();
component.getVersionWithArtifact();
@@ -97,8 +96,8 @@ describe('ProductVersionActionComponent', () => {
);
expect(component.versions()).toEqual(['Version 1.0', 'Version 2.0']);
- expect(component.versionMap.get('Version 1.0')).toEqual([mockArtifct1]);
- expect(component.versionMap.get('Version 2.0')).toEqual([mockArtifct2]);
+ expect(component.versionMap.get('Version 1.0')).toEqual([mockArtifact1]);
+ expect(component.versionMap.get('Version 2.0')).toEqual([mockArtifact2]);
expect(component.selectedVersion()).toBe('Version 1.0');
});
@@ -107,7 +106,7 @@ describe('ProductVersionActionComponent', () => {
component.selectedArtifact = 'https://example.com/download';
spyOn(component, 'onUpdateInstallationCount');
- component.downloadArifact();
+ component.downloadArtifact();
expect(window.open).toHaveBeenCalledWith(
'https://example.com/download',
@@ -135,61 +134,34 @@ describe('ProductVersionActionComponent', () => {
});
function mockApiWithExpectedResponse() {
- const mockArtifct1 = {
+ const mockArtifact1 = {
name: 'Example Artifact1',
downloadUrl: 'https://example.com/download',
- isProductArtifact: true
- } as Artifact;
- const mockArtifct2 = {
+ isProductArtifact: true, label: 'Example Artifact1',
+ } as ItemDropdown;
+ const mockArtifact2 = {
name: 'Example Artifact2',
downloadUrl: 'https://example.com/download',
+ label: 'Example Artifact2',
isProductArtifact: true
- } as Artifact;
+ } as ItemDropdown;
const mockData = [
{
version: '1.0',
- artifactsByVersion: [mockArtifct1]
+ artifactsByVersion: [mockArtifact1]
},
{
version: '2.0',
- artifactsByVersion: [mockArtifct2]
+ artifactsByVersion: [mockArtifact2]
}
];
productServiceMock.sendRequestToProductDetailVersionAPI.and.returnValue(
of(mockData)
);
- return { mockArtifct1, mockArtifct2 };
+ return { mockArtifact1: mockArtifact1, mockArtifact2: mockArtifact2 };
}
- it('should toggle isVersionsDropDownShow on calling onShowVersions', () => {
- const initialState = component.isVersionsDropDownShow();
-
- component.onShowVersions();
- expect(component.isVersionsDropDownShow()).toBe(!initialState);
-
- component.onShowVersions();
- expect(component.isVersionsDropDownShow()).toBe(initialState);
- });
-
- it('should not call onShowVersions if dropdown is not shown', () => {
- spyOn(component, 'isVersionsDropDownShow').and.returnValue(false);
- spyOn(component, 'onShowVersions');
- elementRef = TestBed.inject(ElementRef) as unknown as MockElementRef;
-
- const outsideEvent = new MouseEvent('click', {
- bubbles: true,
- cancelable: true,
- view: window
- });
-
- elementRef.nativeElement.contains.and.returnValue(false);
-
- document.dispatchEvent(outsideEvent);
-
- expect(component.onShowVersions).not.toHaveBeenCalled();
- });
-
it('should open a new tab with the selected artifact URL', () => {
const mockWindowOpen = jasmine.createSpy('windowOpen').and.returnValue({
blur: jasmine.createSpy('blur')
@@ -204,7 +176,7 @@ describe('ProductVersionActionComponent', () => {
component.selectedArtifact = 'http://example.com/artifact';
// Call the method
- component.downloadArifact();
+ component.downloadArtifact();
// Check if window.open was called with the correct URL and target
expect(window.open).toHaveBeenCalledWith(
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 5eaa2fe5c..0bcf19261 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
@@ -1,29 +1,30 @@
import {
AfterViewInit,
- Component,
+ Component, computed,
ElementRef, EventEmitter,
- HostListener,
inject,
Input,
- model, Output,
+ model, Output, Signal,
signal,
WritableSignal
} from '@angular/core';
import { ThemeService } from '../../../../core/services/theme/theme.service';
-import { TranslateModule, TranslateService } from '@ngx-translate/core';
+import { TranslateModule } from '@ngx-translate/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ProductService } from '../../product.service';
-import { Artifact } from '../../../../shared/models/vesion-artifact.model';
import { Tooltip } from 'bootstrap';
import { ProductDetailService } from '../product-detail.service';
import { RoutingQueryParamService } from '../../../../shared/services/routing.query.param.service';
+import { CommonDropdownComponent } from '../../../../shared/components/common-dropdown/common-dropdown.component';
+import { LanguageService } from '../../../../core/services/language/language.service';
+import { ItemDropdown } from '../../../../shared/models/item-dropdown.model';
const delayTimeBeforeHideMessage = 2000;
@Component({
selector: 'app-product-version-action',
standalone: true,
- imports: [CommonModule, TranslateModule, FormsModule],
+ imports: [CommonModule, TranslateModule, FormsModule, CommonDropdownComponent],
templateUrl: './product-detail-version-action.component.html',
styleUrl: './product-detail-version-action.component.scss'
})
@@ -33,22 +34,29 @@ export class ProductDetailVersionActionComponent implements AfterViewInit {
productId!: string;
selectedVersion = model
('');
versions: WritableSignal = signal([]);
- artifacts: WritableSignal = signal([]);
+ versionDropdown : Signal = computed(() => {
+ return this.versions().map(version => ({
+ value: version,
+ label: version
+ }));
+ });
+
+ artifacts: WritableSignal = signal([]);
isDevVersionsDisplayed = signal(false);
isDropDownDisplayed = signal(false);
- isVersionsDropDownShow = signal(false);
isDesignerEnvironment = signal(false);
isInvalidInstallationEnvironment = signal(false);
designerVersion = '';
- selectedArtifact = '';
- versionMap: Map = new Map();
+ selectedArtifact: string | undefined = '';
+ selectedArtifactName:string | undefined = '';
+ versionMap: Map = new Map();
routingQueryParamService = inject(RoutingQueryParamService);
themeService = inject(ThemeService);
- translateService = inject(TranslateService);
productService = inject(ProductService);
productDetailService = inject(ProductDetailService);
elementRef = inject(ElementRef);
+ languageService = inject(LanguageService);
ngAfterViewInit() {
const tooltipTriggerList = [].slice.call(
@@ -60,10 +68,7 @@ export class ProductDetailVersionActionComponent implements AfterViewInit {
this.isDesignerEnvironment.set(
this.routingQueryParamService.isDesignerEnv()
);
- }
- onShowVersions() {
- this.isVersionsDropDownShow.set(!this.isVersionsDropDownShow());
}
getInstallationTooltipText() {
@@ -74,14 +79,25 @@ export class ProductDetailVersionActionComponent implements AfterViewInit {
(minimum version 9.2.0)`;
}
- onSelectVersion() {
+ onSelectVersion(version : string) {
+ this.selectedVersion.set(version);
this.artifacts.set(this.versionMap.get(this.selectedVersion()) ?? []);
-
+ this.artifacts().forEach(artifact => {
+ if(artifact.name) {
+ artifact.label = artifact.name;
+ }
+ });
if (this.artifacts().length !== 0) {
- this.selectedArtifact = this.artifacts()[0].downloadUrl;
+ this.selectedArtifactName = this.artifacts()[0].name ?? '';
+ this.selectedArtifact = this.artifacts()[0].downloadUrl ?? '';
}
}
+ onSelectArtifact(artifact: ItemDropdown) {
+ this.selectedArtifactName = artifact.name;
+ this.selectedArtifact = artifact.downloadUrl;
+ }
+
onShowDevVersion(event: Event) {
event.preventDefault();
this.isDevVersionsDisplayed.set(!this.isDevVersionsDisplayed());
@@ -96,7 +112,7 @@ export class ProductDetailVersionActionComponent implements AfterViewInit {
}
getVersionWithArtifact() {
- this.sanitizeDataBeforFetching();
+ this.sanitizeDataBeforeFetching();
this.productService
.sendRequestToProductDetailVersionAPI(
@@ -111,25 +127,25 @@ export class ProductDetailVersionActionComponent implements AfterViewInit {
...currentVersions,
version
]);
+
if (!this.versionMap.get(version)) {
this.versionMap.set(version, item.artifactsByVersion);
}
});
if (this.versions().length !== 0) {
this.selectedVersion.set(this.versions()[0]);
- this.onSelectVersion();
}
});
}
- sanitizeDataBeforFetching() {
+ sanitizeDataBeforeFetching() {
this.versions.set([]);
this.artifacts.set([]);
this.selectedArtifact = '';
this.selectedVersion.set('');
}
- downloadArifact() {
+ downloadArtifact() {
this.onUpdateInstallationCount();
const newTab = window.open(this.selectedArtifact, '_blank');
if (newTab) {
@@ -138,16 +154,6 @@ export class ProductDetailVersionActionComponent implements AfterViewInit {
window.focus();
}
- @HostListener('document:click', ['$event'])
- handleClickOutside(event: MouseEvent) {
- if (
- !this.elementRef.nativeElement.contains(event.target) &&
- this.isVersionsDropDownShow()
- ) {
- this.onShowVersions();
- }
- }
-
onUpdateInstallationCount() {
this.productService
.sendRequestToUpdateInstallationCount(this.productId)
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 73592b411..fe8de3ed1 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
@@ -10,33 +10,48 @@
themeService.isDarkMode() ? 'text-light' : 'text-link-blue'
">
<
- {{ 'common.product.detail.backToMainPage' | translate }}
+
+ {{ 'common.product.detail.backToMainPage' | translate }}
+