Skip to content

Commit

Permalink
fix(admin-ui): Fix renaming of multiple product options at once
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbromley committed Jun 18, 2024
1 parent 18d200c commit 3de60b2
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
unicodePatternValidator,
UpdateProductInput,
UpdateProductMutation,
UpdateProductOptionInput,
UpdateProductVariantInput,
UpdateProductVariantsMutation,
} from '@vendure/admin-ui/core';
Expand Down Expand Up @@ -256,28 +255,6 @@ export class ProductDetailComponent
});
}

updateProductOption(input: UpdateProductOptionInput & { autoUpdate: boolean }) {
combineLatest(this.entity$, this.languageCode$)
.pipe(
take(1),
mergeMap(([product, languageCode]) =>
this.productDetailService.updateProductOption(input, product, languageCode),
),
)
.subscribe(
() => {
this.notificationService.success(_('common.notify-update-success'), {
entity: 'ProductOption',
});
},
err => {
this.notificationService.error(_('common.notify-update-error'), {
entity: 'ProductOption',
});
},
);
}

removeProductFacetValue(facetValueId: string) {
const productGroup = this.detailForm;
const currentFacetValueIds = productGroup.value.facetValueIds ?? [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export class ProductOptionsEditorComponent extends BaseDetailComponent<ProductWi
take(1),
mergeMap(([{ optionGroups }, languageCode, product]) => {
const updateOperations: Array<Observable<any>> = [];
const updatedProductOptionInputs: UpdateProductOptionInput[] = [];
for (const optionGroupForm of this.getOptionGroups()) {
if (optionGroupForm.dirty) {
const optionGroupEntity = optionGroups.find(
Expand Down Expand Up @@ -127,17 +128,21 @@ export class ProductOptionsEditorComponent extends BaseDetailComponent<ProductWi
optionForm,
languageCode,
);
updateOperations.push(
this.productDetailService.updateProductOption(
{ ...input, autoUpdate: this.autoUpdateVariantNames },
product,
languageCode,
),
);
updatedProductOptionInputs.push(input);
}
}
}
}
if (updatedProductOptionInputs.length) {
updateOperations.push(
this.productDetailService.updateProductOptions(
updatedProductOptionInputs,
this.autoUpdateVariantNames,
product,
languageCode,
),
);
}
return forkJoin(updateOperations);
}),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,13 @@ export class ProductDetailService {
);
}

updateProductOption(
input: UpdateProductOptionInput & { autoUpdate: boolean },
updateProductOptions(
inputs: UpdateProductOptionInput[],
autoUpdateProductNames: boolean,
product: NonNullable<GetProductDetailQuery['product']>,
languageCode: LanguageCode,
) {
const variants$ = input.autoUpdate
const variants$ = autoUpdateProductNames
? this.dataService.product
.getProductVariantsForProduct({}, product.id)
.mapSingle(({ productVariants }) => productVariants.items)
Expand All @@ -237,44 +238,67 @@ export class ProductDetailService {
return variants$.pipe(
mergeMap(variants => {
let updateProductVariantNames$: Observable<any> = of([]);
if (input.autoUpdate) {
// Update any ProductVariants' names which include the option name
let oldOptionName: string | undefined;
const newOptionName = findTranslation(input, languageCode)?.name;
if (!newOptionName) {
updateProductVariantNames$ = of([]);
if (autoUpdateProductNames) {
const replacementMap = new Map<string, string>();

for (const input of inputs) {
const newOptionName = findTranslation(input, languageCode)?.name;
let oldOptionName: string | undefined;
for (const variant of variants) {
if (oldOptionName) {
continue;
}
if (variant.options.map(o => o.id).includes(input.id)) {
if (!oldOptionName) {
oldOptionName = findTranslation(
variant.options.find(o => o.id === input.id),
languageCode,
)?.name;
}
}
}
if (oldOptionName && newOptionName) {
replacementMap.set(oldOptionName, newOptionName);
}
}

const variantsToUpdate: UpdateProductVariantInput[] = [];
for (const variant of variants) {
if (variant.options.map(o => o.id).includes(input.id)) {
if (!oldOptionName) {
oldOptionName = findTranslation(
variant.options.find(o => o.id === input.id),
languageCode,
)?.name;
if (replacementMap.size) {
const oldOptionNames = Array.from(replacementMap.keys());
for (const variant of variants) {
const variantName = findTranslation(variant, languageCode)?.name;
if (!variantName) {
continue;
}
const variantName = findTranslation(variant, languageCode)?.name || '';
if (oldOptionName && newOptionName && variantName.includes(oldOptionName)) {
variantsToUpdate.push({
id: variant.id,
translations: [
{
languageCode,
name: replaceLast(variantName, oldOptionName, newOptionName),
},
],
});
if (!oldOptionNames.some(oldOptionName => variantName.includes(oldOptionName))) {
continue;
}
const updatedVariantName = oldOptionNames.reduce(
(name, oldOptionName) =>
replaceLast(name, oldOptionName, replacementMap.get(oldOptionName)!),
variantName,
);
variantsToUpdate.push({
id: variant.id,
translations: [
{
languageCode,
name: updatedVariantName,
},
],
});
}
}
if (variantsToUpdate.length) {
updateProductVariantNames$ =
this.dataService.product.updateProductVariants(variantsToUpdate);
} else {
updateProductVariantNames$ = of([]);
}
}
return this.dataService.product
.updateProductOption(input)
.pipe(mergeMap(() => updateProductVariantNames$));
return forkJoin(
inputs.map(input => this.dataService.product.updateProductOption(input)),
).pipe(mergeMap(() => updateProductVariantNames$));
}),
);
}
Expand Down

0 comments on commit 3de60b2

Please sign in to comment.