diff --git a/src/app/app-products.module.ts b/src/app/app-products.module.ts index d26ba40165e2953f0d7adc3282bd6d8430053b66..a83a0f98d10299a08f7a714f1ee36ff6f7e47388 100644 --- a/src/app/app-products.module.ts +++ b/src/app/app-products.module.ts @@ -24,7 +24,7 @@ import { PreviewMarketPlaceItemComponent } from './p_product/marketplace/preview import { AssignProductOfferingsComponent } from './p_product/admin/productCatalogManagement/edit-product-categories/assign-product-offerings/assign-product-offerings.component'; import { AssignSubcategoriesComponent } from './p_product/admin/productCatalogManagement/edit-product-categories/assign-subcategories/assign-subcategories.component'; import { ConfirmCharacteristicAssignmentComponent } from './p_product/admin/productCatalogManagement/edit-product-specs/assign-service-specification/confirm-characteristic-assignment/confirm-characteristic-assignment.component'; - +import { SortByValuePipe } from './p_product/admin/productCatalogManagement/edit-product-offerings/sort-by-value.pipe'; @NgModule({ declarations: [ @@ -48,7 +48,8 @@ import { ConfirmCharacteristicAssignmentComponent } from './p_product/admin/prod EditProductOfferingsComponent, PreviewMarketPlaceItemComponent, AssignProductOfferingsComponent, - AssignSubcategoriesComponent + AssignSubcategoriesComponent, + SortByValuePipe ], imports: [ CommonModule, diff --git a/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.html b/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.html index e62fdea4c0bb1feade6e47216e454c7256878d5b..f431895c68cd1de92d119f25c658c672c5ece328 100644 --- a/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.html +++ b/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.html @@ -151,6 +151,135 @@ + +
+
+
+
+
+ +
+
+
Please select a Linked Product Specification in the "Main Properties" tab first.
+
+
+ +
+ +
+
Choose Configurable Characteristics to expose from: + {{editForm.value.productSpecification.name}} + +
+ Select the configurable characteristics to include in the product offering. Expand to select specific characteristic values. +
+ +
+ No characteristics found in the selected Product Specification. +
+ + + + + +
+ + + +
+ {{char.name}} + {{char.valueType}} +
+ +
+ {{ getSelectedValuesCount(char) }} / {{ char.productSpecCharacteristicValue.length }} values +
+
+
+ + +
+

{{char.description}}

+
+

+ This characteristic has no pre-defined values. +

+
+ +
+

Select the characteristic values for this offering:

+ +
+
+ + + + + + {{val.value.alias}}: {{val.value.value}} + - ({{val.unitOfMeasure}}) + + + {{val.value.value}} + ({{val.unitOfMeasure}}) + + + + Empty Value + + + +
+
+ +
+ + +
+
+
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+
+ + +
+
+
+ + + diff --git a/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.scss b/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.scss index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c6dda67cce3cc746ddc24b94802518bf001bd975 100644 --- a/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.scss +++ b/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.scss @@ -0,0 +1,3 @@ +.nav-link:hover { + cursor: pointer; +} diff --git a/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.ts b/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.ts index a7e5b6f15fdc9d148b4c63db9213872e9dd7d946..90aed37f7d862e9662a647bcae6f9f8eef30b965 100644 --- a/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.ts +++ b/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/edit-product-offerings.component.ts @@ -1,15 +1,19 @@ -import { trigger } from '@angular/animations'; -import { SelectionChange } from '@angular/cdk/collections'; import { Component, OnInit } from '@angular/core'; +import { trigger } from '@angular/animations'; import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; -import { MatOptionSelectionChange } from '@angular/material/core'; import { MatDialog, MatDialogRef } from '@angular/material/dialog'; +import { MatCheckboxChange } from '@angular/material/checkbox'; import { MatSelectChange } from '@angular/material/select'; import { ActivatedRoute, ActivationEnd, Router } from '@angular/router'; import { ToastrService } from 'ngx-toastr'; -import { relative } from 'path'; import { Subscription } from 'rxjs'; -import { ProductOffering, ProductOfferingCreate, ProductOfferingUpdate, ProductSpecification } from 'src/app/openApis/productCatalogManagement/models'; +import { + ProductOffering, + ProductOfferingCreate, + ProductOfferingUpdate, + ProductSpecification, + ProductSpecificationCharacteristicRes +} from 'src/app/openApis/productCatalogManagement/models'; import { ProductOfferingService, ProductSpecificationService } from 'src/app/openApis/productCatalogManagement/services'; import { fadeIn } from 'src/app/shared/animations/animations'; import { AppService } from 'src/app/shared/services/app.service'; @@ -37,17 +41,22 @@ export class EditProductOfferingsComponent implements OnInit { offeringNotFound: boolean = false finishedLoading: boolean = false newOffering = false - productSpecifications: ProductSpecification[] + + currentLinkedSpec: ProductSpecification; + availableSpecCharacteristics: ProductSpecificationCharacteristicRes[] = []; + + selectedCharacteristics: Set = new Set(); + selectedCharValues: Map = new Map(); - listItems = ["Main Properties"] + listItems = ["Main Properties", "Product Offering Characteristics"] activeListItem = "Main Properties" + lifecycleStatuses = ["In study", "In design", "In test", "Active", "Launched", "Retired", "Obsolete", "Rejected"] - editForm = new UntypedFormGroup({ + editForm = new UntypedFormGroup({ description: new UntypedFormControl(), lifecycleStatus: new UntypedFormControl("In design", Validators.required), name: new UntypedFormControl(null, Validators.required), - // isBundle: new FormControl(), validFor: new UntypedFormGroup({ endDateTime: new UntypedFormControl(new Date(new Date().setFullYear(new Date().getFullYear()+20)), Validators.required), startDateTime: new UntypedFormControl(new Date(), Validators.required) @@ -55,26 +64,20 @@ export class EditProductOfferingsComponent implements OnInit { version: new UntypedFormControl("0.1.0", Validators.required), productSpecification: new UntypedFormControl() }) - - lifecycleStatuses = ["In study", "In design", "In test", "Active", "Launched", "Retired", "Obsolete", "Rejected"] subscriptions = new Subscription() - // valueChangeSubscription$: any - ngOnInit(): void { this.initSubscriptions() this.listProductSpecifications() - if (this.activatedRoute.snapshot.params.id) - { + if (this.activatedRoute.snapshot.params.id) { this.offeringID = this.activatedRoute.snapshot.params.id this.retrieveOffering() } else { this.newOffering = true this.finishedLoading = true } - } initSubscriptions() { @@ -88,38 +91,6 @@ export class EditProductOfferingsComponent implements OnInit { )) } - - onSpecificationChange(event: MatSelectChange) { - const dialogRef = this.dialog.open(CopySpecificationPropertiesComponent, { autoFocus: true }) - - dialogRef.afterClosed().subscribe(confirmCopy => { - if (confirmCopy) { - this.editForm.patchValue({ - name: event.value.name, - description: event.value.description, - }) - } - }) - } - - - - selectListitem(item: string) { - if (this.editForm.pristine) { - this.activeListItem = item - } else { - const dialogRef = this.dialog.open(DiscardChangesComponent, {autoFocus: true}) - - dialogRef.afterClosed().subscribe (discardChanges => { - if (discardChanges) { - this.editForm.patchValue(this.offering) - this.editForm.markAsPristine() - this.activeListItem = item - } - }) - } - } - listProductSpecifications() { this.specService.listProductSpecification({}).subscribe( data => this.productSpecifications = data, @@ -135,21 +106,17 @@ export class EditProductOfferingsComponent implements OnInit { if (this.offering) { this.finishedLoading = true this.editForm.reset() - //populate General Panel Info if (!this.offering.validFor) this.offering.validFor = { endDateTime: new Date(new Date().setFullYear(new Date().getFullYear()+20)).toISOString(), startDateTime: new Date().toISOString() } + this.editForm.patchValue(this.offering) this.editForm.markAsPristine() if (this.offering.productSpecification) { - this.editForm.patchValue({productSpecification: this.productSpecifications.find(el => el.id === this.offering.productSpecification.id) }) + const specRef = this.productSpecifications.find(el => el.id === this.offering.productSpecification.id); + this.editForm.patchValue({ productSpecification: specRef }); + + this.loadLinkedSpecDetails(this.offering.productSpecification.id, true); } - - //populate Product Specification Relationship - // this.filteredServiceSpecificationRel$ = this.serviceSpecificationRelationshipFilterCtrl.valueChanges.pipe( - // startWith(null), - // map( (value:null | string) => value ? this._filterOnRelatedSpecs(value) : this.spec.serviceSpecification.slice() ) - // ) - } else { this.offeringNotFound = true @@ -158,59 +125,414 @@ export class EditProductOfferingsComponent implements OnInit { ) } + + loadLinkedSpecDetails(specId: string, isInitialLoad: boolean = false) { + this.specService.retrieveProductSpecification({ id: specId }).subscribe( + fullSpec => { + this.currentLinkedSpec = fullSpec; + this.availableSpecCharacteristics = fullSpec.productSpecCharacteristic || []; + if (!isInitialLoad) { + this.selectedCharacteristics.clear(); + this.selectedCharValues.clear(); + // this.selectAllCharacteristics(); + } + + if (isInitialLoad && this.offering.prodSpecCharValueUse) { + this.offering.prodSpecCharValueUse.forEach(offeringChar => { + this.selectedCharacteristics.add(offeringChar.name); + + const specCharDef = this.availableSpecCharacteristics.find(c => c.name === offeringChar.name); + + const selectedUUIDs: string[] = []; + + if (offeringChar.productSpecCharacteristicValue && specCharDef) { + offeringChar.productSpecCharacteristicValue.forEach(savedVal => { + const matchingSpecVal = specCharDef.productSpecCharacteristicValue?.find(specVal => { + const sameValue = specVal.value?.value === savedVal.value?.value; + const sameAlias = specVal.value?.alias === savedVal.value?.alias; + return sameValue && sameAlias; + }); + + if (matchingSpecVal && matchingSpecVal.uuid) { + selectedUUIDs.push(matchingSpecVal.uuid); + } + }); + } + this.selectedCharValues.set(offeringChar.name, selectedUUIDs); + }); + } + + }, + error => this.toastrService.error("Failed to load full spec details", error) + ); + } + + // ------------------------------------------------------------------ + + onSpecificationChange(event: MatSelectChange) { + + const dialogRef = this.dialog.open(CopySpecificationPropertiesComponent, { autoFocus: true }); + + dialogRef.afterClosed().subscribe(confirmCopy => { + if (confirmCopy) { + this.editForm.patchValue({ + name: event.value.name, + description: event.value.description, + }); + + } + }) + + this.selectedCharacteristics.clear(); + this.availableSpecCharacteristics = []; + if (event.value && event.value.id) { + this.loadLinkedSpecDetails(event.value.id, false); + } + + } + + isCharacteristicSelected(char: ProductSpecificationCharacteristicRes): boolean { + return this.selectedCharacteristics.has(char.name); + } + + onCharacteristicToggle(char: ProductSpecificationCharacteristicRes, event: MatCheckboxChange) { + if (event.checked) { + this.selectedCharacteristics.add(char.name); + // if (!this.selectedCharValues.has(char.name)) { + // this.selectAllValues(char); + // } + } else { + this.selectedCharacteristics.delete(char.name); + this.selectedCharValues.set(char.name, []); + } + this.editForm.markAsDirty(); + } + + isValueSelected(char: ProductSpecificationCharacteristicRes, val: any): boolean { + if (!val || !val.uuid) return false; + + const selectedUUIDs = this.selectedCharValues.get(char.name); + return selectedUUIDs ? selectedUUIDs.includes(val.uuid) : false; + } + + getSelectedValuesCount(char: ProductSpecificationCharacteristicRes): number { + const selectedArray = this.selectedCharValues.get(char.name); + return selectedArray ? selectedArray.length : 0; + } + + onValueToggle(char: ProductSpecificationCharacteristicRes, val: any, event: MatCheckboxChange) { + if (!val || !val.uuid) return; + + let selectedUUIDs = this.selectedCharValues.get(char.name); + if (!selectedUUIDs) { + selectedUUIDs = []; + this.selectedCharValues.set(char.name, selectedUUIDs); + } + + const uuid = val.uuid; + + if (event.checked) { + if (!selectedUUIDs.includes(uuid)) { + selectedUUIDs.push(uuid); + } + } else { + const index = selectedUUIDs.indexOf(uuid); + if (index > -1) { + selectedUUIDs.splice(index, 1); + } + } + this.editForm.markAsDirty(); + } + + selectAllCharacteristics() { + this.availableSpecCharacteristics.forEach(c => { + this.selectedCharacteristics.add(c.name); + // this.selectAllValues(c); + }); + this.editForm.markAsDirty(); + } + + deselectAllCharacteristics() { + this.selectedCharacteristics.clear(); + this.selectedCharValues.clear(); + this.editForm.markAsDirty(); + } + + selectAllValues(char: ProductSpecificationCharacteristicRes) { + const allUUIDs: string[] = []; + + if (char.productSpecCharacteristicValue) { + char.productSpecCharacteristicValue.forEach(v => { + if (v.uuid) { + allUUIDs.push(v.uuid); + } + }); + } + this.selectedCharValues.set(char.name, allUUIDs); + this.editForm.markAsDirty(); + } + + deselectAllValues(char: ProductSpecificationCharacteristicRes) { + + this.selectedCharValues.set(char.name, []); + this.editForm.markAsDirty(); + + } + + // ------------------------------------------------------------------ + updateOfferingGeneral() { if (this.editForm.valid) { - const updateObj: ProductOfferingCreate | ProductOfferingUpdate = { - description: this.editForm.value.description, - lifecycleStatus: this.editForm.value.lifecycleStatus, - name: this.editForm.value.name, - validFor: this.editForm.value.validFor, - version: this.editForm.value.version + const formValue = this.editForm.value; + const linkedSpec = this.currentLinkedSpec || formValue.productSpecification; + + let productSpecRef: any = undefined; + if (linkedSpec) { + productSpecRef = { id: linkedSpec.id, name: linkedSpec.name }; + if (linkedSpec.version) productSpecRef.version = linkedSpec.version; } - - if (this.editForm.value.productSpecification) { - updateObj.productSpecification = {name: this.editForm.value.productSpecification.name, id: this.editForm.value.productSpecification.id} + + let characteristicsToSave: any[] = []; + + if (!this.newOffering && this.offering && this.offering.prodSpecCharValueUse) { + const originalSpecId = this.offering.productSpecification?.id; + const currentSpecId = linkedSpec?.id; + + if (originalSpecId === currentSpecId) { + characteristicsToSave = this.offering.prodSpecCharValueUse; + } else { + characteristicsToSave = []; + } } + + const updateObj: ProductOfferingCreate | ProductOfferingUpdate = { + name: formValue.name, + description: formValue.description || '', + lifecycleStatus: formValue.lifecycleStatus, + version: formValue.version, + validFor: {"startDateTime": formValue.validFor.startDateTime, "endDateTime": formValue.validFor.endDateTime}, + isSellable: true, + statusReason: '', + productSpecification: productSpecRef, + + isBundle: linkedSpec?.isBundle || false, + attachment: linkedSpec?.attachment || [], + + prodSpecCharValueUse: characteristicsToSave, + + serviceCandidate: (linkedSpec && (linkedSpec as any).serviceSpecification && (linkedSpec as any).serviceSpecification.length > 0) + ? { + id: (linkedSpec as any).serviceSpecification[0].id, + name: (linkedSpec as any).serviceSpecification[0].name, + version: (linkedSpec as any).serviceSpecification[0].version, + '@type': 'ServiceCandidateRef' + } + : undefined, + + resourceCandidate: (linkedSpec && (linkedSpec as any).resourceSpecification && (linkedSpec as any).resourceSpecification.length > 0) + ? { + id: (linkedSpec as any).resourceSpecification[0].id, + name: (linkedSpec as any).resourceSpecification[0].name, + version: (linkedSpec as any).resourceSpecification[0].version, + '@type': 'ResourceCandidateRef' + } + : undefined, + + serviceLevelAgreement: (linkedSpec as any).serviceLevelAgreement || undefined, + + agreement: [], + bundledProductOffering: [], + category: [], + channel: [], + marketSegment: [], + place: [], + productOfferingPrice: [], + productOfferingTerm: [], + '@type': 'ProductOffering' + }; - let updatedOffering: ProductOffering + let updatedOffering: ProductOffering; if (this.newOffering) { this.offeringService.createProductOffering(updateObj).subscribe( data => { updatedOffering = data }, - error => console.error(error), + error => { console.error(error); this.toastrService.error("Failed to create offering"); }, () => { - this.newOffering = false - this.router.navigate([updatedOffering.id], {relativeTo: this.activatedRoute}) - this.toastrService.success("Product Offering was successfully created") - this.refreshProductOffering(updatedOffering) + this.newOffering = false; + this.router.navigate([updatedOffering.id], {relativeTo: this.activatedRoute}); + this.toastrService.success("Product Offering created. Please configure characteristics in the next tab."); + this.refreshProductOffering(updatedOffering); } - ) - } - else { + ); + } else { this.offeringService.patchProductOffering({ id: this.offeringID, productOffering: updateObj }).subscribe( data => { updatedOffering = data }, - error => console.error(error), + error => { console.error(error); this.toastrService.error("Failed to update offering"); }, () => { - this.toastrService.success("Product Offering was successfully updated") - this.refreshProductOffering(updatedOffering) + this.toastrService.success("Product Offering General Info updated"); + this.refreshProductOffering(updatedOffering); } - ) + ); } } - - } + } + + // ------------------------------------------------------------------ + + updateOfferingCharacteristics() { + if (!this.offeringID) { + this.toastrService.error("Please save the General Properties first to create the Offering."); + return; + } + + if (!this.currentLinkedSpec) { + this.toastrService.warning("No Product Specification linked."); + return; + } + + const charsToMap = this.currentLinkedSpec.productSpecCharacteristic?.filter( + char => this.selectedCharacteristics.has(char.name) + ) || []; + + const mappedChars = this.mapSpecCharacteristicsToOffering(charsToMap, this.currentLinkedSpec); + + const patchObj: ProductOfferingUpdate = { + prodSpecCharValueUse: mappedChars + }; + + let updatedOffering: ProductOffering; + + this.offeringService.patchProductOffering({ id: this.offeringID, productOffering: patchObj }).subscribe( + data => { updatedOffering = data }, + error => { + console.error(error); + this.toastrService.error("Failed to update characteristics: " + (error.error?.message || error.message)); + }, + () => { + this.toastrService.success("Product Offering Characteristics updated successfully"); + this.refreshProductOffering(updatedOffering); + } + ); + } + + + private mapSpecCharacteristicsToOffering(specChars: ProductSpecificationCharacteristicRes[], linkedSpec: ProductSpecification | null): any[] { + if (!specChars) return []; + + return specChars.map(char => { + + let mappedValues = []; + if (char.productSpecCharacteristicValue && char.productSpecCharacteristicValue.length > 0) { + const selectedUUIDs = this.selectedCharValues.get(char.name); + + mappedValues = char.productSpecCharacteristicValue + .filter(val => { + return val.uuid && selectedUUIDs && selectedUUIDs.includes(val.uuid); + }) + .map(val => { + const { uuid, ...rest } = val as any; + return rest; + }); + } + + const charId = char.uuid; + // const charUuid = char.uuid; + let charVersion = char.version; + if (!charVersion && linkedSpec) charVersion = linkedSpec.version; + + const charRef: any = { + id: charId, + name: char.name, + '@type': 'ProductSpecificationCharacteristic', + '@referredType': 'ProductSpecificationCharacteristic' + }; + // if (charUuid) charRef.uuid = charUuid; + if (charVersion) charRef.version = charVersion; + + let parentSpecRef: any = undefined; + if (linkedSpec) { + parentSpecRef = { + id: linkedSpec.id, + name: linkedSpec.name, + version: linkedSpec.version, + '@type': 'ProductSpecificationRef', + '@referredType': 'ProductSpecification' + }; + } + + return { + uuid: char.uuid, + lastUpdate: char.lastUpdate, + lifecyclestatusEnum: 'In Study', + '@baseType': 'ProductSpecCharacteristicUse', + '@type': 'ProductSpecCharacteristicUse', + '@schemaLocation': char['@schemaLocation'], + href: char.href, + name: char.name, + description: char.description, + lifecycleStatus: char.lifecycleStatus, + version: char.version, + minCardinality: char.minCardinality, + maxCardinality: char.maxCardinality, + valueType: char.valueType, + validFor: char.validFor, + productSpecCharacteristicValue: mappedValues, + // productSpecificationCharacteristic: charRef, + productSpecification: parentSpecRef + }; + }); + } refreshProductOffering(updatedOffering : ProductOffering) { this.offeringID = updatedOffering.id this.retrieveOffering() } + selectListitem(item: string) { + if (this.editForm.pristine) { + this.activeListItem = item; + } else { + const dialogRef = this.dialog.open(DiscardChangesComponent, { autoFocus: true }); + + dialogRef.afterClosed().subscribe(discardChanges => { + if (discardChanges) { + this.editForm.reset(); + + this.selectedCharacteristics.clear(); + this.selectedCharValues.clear(); + this.availableSpecCharacteristics = []; + this.currentLinkedSpec = null; + + if (this.offering) { + if (!this.offering.validFor) { + this.offering.validFor = { + endDateTime: new Date(new Date().setFullYear(new Date().getFullYear()+20)).toISOString(), + startDateTime: new Date().toISOString() + }; + } + this.editForm.patchValue(this.offering); + + if (this.offering.productSpecification) { + const specRef = this.productSpecifications.find(el => el.id === this.offering.productSpecification.id); + this.editForm.patchValue({ productSpecification: specRef }); + + this.loadLinkedSpecDetails(this.offering.productSpecification.id, true); + } + } + + this.editForm.markAsPristine(); + this.activeListItem = item; + } + }); + } + } + ngOnDestroy() { this.subscriptions.unsubscribe() } - } + @Component({ selector: 'app-discard-changes', templateUrl: 'discard-changes.component.html', @@ -249,4 +571,4 @@ export class CopySpecificationPropertiesComponent { onYesClick(): void { this.dialogRef.close(true) } -} +} \ No newline at end of file diff --git a/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/sort-by-value.pipe.ts b/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/sort-by-value.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..282ce9b86cf02979220e7837773c96ca404d8760 --- /dev/null +++ b/src/app/p_product/admin/productCatalogManagement/edit-product-offerings/sort-by-value.pipe.ts @@ -0,0 +1,21 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'sortByValue' +}) +export class SortByValuePipe implements PipeTransform { + + transform(values: any[]): any[] { + if (!values || !Array.isArray(values)) { + return []; + } + + return [...values].sort((a, b) => { + const labelA = (a.value?.alias || a.value?.value || '').toString().toLowerCase(); + const labelB = (b.value?.alias || b.value?.value || '').toString().toLowerCase(); + + return labelA.localeCompare(labelB, undefined, { numeric: true }); + }); + } + +} \ No newline at end of file diff --git a/src/app/p_product/admin/productCatalogManagement/list-product-offerings/list-product-offerings.component.ts b/src/app/p_product/admin/productCatalogManagement/list-product-offerings/list-product-offerings.component.ts index 102cb45844cf58155a49e1ec599f049f5f84aba8..505335ed959fa5818e6dd93a927eef8d948d46d5 100644 --- a/src/app/p_product/admin/productCatalogManagement/list-product-offerings/list-product-offerings.component.ts +++ b/src/app/p_product/admin/productCatalogManagement/list-product-offerings/list-product-offerings.component.ts @@ -45,6 +45,8 @@ export class ListProductOfferingsComponent implements OnInit { error => { console.error(error) }, () => { this.dataSource.data = this.productOfferings + this.sort.active = 'lastUpdate' + this.sort.direction = 'desc' this.dataSource.sort = this.sort this.dataSource.paginator = this.paginator; this.dataSource.sortingDataAccessor = (item, property): string | number => {