Просмотр исходного кода

fix(admin-ui): Fix renaming of multiple product options at once

Fixes #2892
Michael Bromley 1 год назад
Родитель
Сommit
3de60b2692

+ 0 - 23
packages/admin-ui/src/lib/catalog/src/components/product-detail/product-detail.component.ts

@@ -23,7 +23,6 @@ import {
     unicodePatternValidator,
     UpdateProductInput,
     UpdateProductMutation,
-    UpdateProductOptionInput,
     UpdateProductVariantInput,
     UpdateProductVariantsMutation,
 } from '@vendure/admin-ui/core';
@@ -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 ?? [];

+ 12 - 7
packages/admin-ui/src/lib/catalog/src/components/product-options-editor/product-options-editor.component.ts

@@ -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(
@@ -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);
                 }),
             )

+ 54 - 30
packages/admin-ui/src/lib/catalog/src/providers/product-detail/product-detail.service.ts

@@ -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)
@@ -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$));
             }),
         );
     }