From 73031714ac51dfe097b83909691bf02144c22a06 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Tue, 17 Sep 2019 16:27:09 +0200 Subject: [PATCH] feat(admin-ui): Enable adding options to single-variant Products Relates to #162 --- .../product-detail.component.ts | 2 +- .../product-variants-editor.component.html | 8 ++-- .../product-variants-editor.component.ts | 29 ++++++++++++-- .../providers/product-detail.service.ts | 40 ++++++++++--------- packages/admin-ui/src/i18n-messages/en.json | 4 ++ 5 files changed, 57 insertions(+), 26 deletions(-) diff --git a/packages/admin-ui/src/app/catalog/components/product-detail/product-detail.component.ts b/packages/admin-ui/src/app/catalog/components/product-detail/product-detail.component.ts index b49a07cd95..6c283912ad 100644 --- a/packages/admin-ui/src/app/catalog/components/product-detail/product-detail.component.ts +++ b/packages/admin-ui/src/app/catalog/components/product-detail/product-detail.component.ts @@ -280,7 +280,7 @@ export class ProductDetailComponent extends BaseDetailComponent
@@ -31,7 +31,7 @@ >
- @@ -49,7 +49,7 @@ @@ -59,7 +59,7 @@ [(ngModel)]="variantFormValues[variant.id].enabled" name="enabled" clrCheckbox - (ngModelChange)="onFormChanged(variantFormValues[variant.id])" + (ngModelChange)="formValueChanged = true" /> diff --git a/packages/admin-ui/src/app/catalog/components/product-variants-editor/product-variants-editor.component.ts b/packages/admin-ui/src/app/catalog/components/product-variants-editor/product-variants-editor.component.ts index 25c2682219..e10ead2acc 100644 --- a/packages/admin-ui/src/app/catalog/components/product-variants-editor/product-variants-editor.component.ts +++ b/packages/admin-ui/src/app/catalog/components/product-variants-editor/product-variants-editor.component.ts @@ -59,9 +59,9 @@ export class ProductVariantsEditorComponent implements OnInit, DeactivateAware { }>; }>; variantFormValues: { [id: string]: VariantInfo } = {}; + product: GetProductVariantOptions.Product; private currencyCode: CurrencyCode; private languageCode: LanguageCode; - private product: GetProductVariantOptions.Product; constructor( private route: ActivatedRoute, @@ -195,9 +195,11 @@ export class ProductVariantsEditorComponent implements OnInit, DeactivateAware { values: [], })); - this.productDetailService - .createProductOptionGroups(newOptionGroups, this.languageCode) + this.confirmDeletionOfDefault() .pipe( + mergeMap(() => + this.productDetailService.createProductOptionGroups(newOptionGroups, this.languageCode), + ), mergeMap(createdOptionGroups => this.addOptionGroupsToProduct(createdOptionGroups)), mergeMap(createdOptionGroups => this.addNewOptionsToGroups(createdOptionGroups)), mergeMap(groupsIds => this.fetchOptionGroups(groupsIds)), @@ -216,6 +218,27 @@ export class ProductVariantsEditorComponent implements OnInit, DeactivateAware { }); } + private confirmDeletionOfDefault(): Observable { + if (this.product.variants.length === 1) { + return this.modalService + .dialog({ + title: _('catalog.confirm-adding-options-delete-default-title'), + body: _('catalog.confirm-adding-options-delete-default-body'), + buttons: [ + { type: 'seconday', label: _('common.cancel') }, + { type: 'danger', label: _('catalog.delete-default-variant'), returnValue: true }, + ], + }) + .pipe( + mergeMap(res => { + return res === true ? of(true) : EMPTY; + }), + ); + } else { + return of(true); + } + } + private addOptionGroupsToProduct( createdOptionGroups: CreateProductOptionGroup.CreateProductOptionGroup[], ): Observable { diff --git a/packages/admin-ui/src/app/catalog/providers/product-detail.service.ts b/packages/admin-ui/src/app/catalog/providers/product-detail.service.ts index 52c8e337b0..a2dc880cb5 100644 --- a/packages/admin-ui/src/app/catalog/providers/product-detail.service.ts +++ b/packages/admin-ui/src/app/catalog/providers/product-detail.service.ts @@ -53,32 +53,17 @@ export class ProductDetailService { .pipe(shareReplay(1)); } - createProduct( + createProductWithVariants( input: CreateProductInput, createVariantsConfig: CreateProductVariantsConfig, languageCode: LanguageCode, ) { const createProduct$ = this.dataService.product.createProduct(input); - const nonEmptyOptionGroups = createVariantsConfig.groups.filter(g => 0 < g.values.length); - const createOptionGroups$ = nonEmptyOptionGroups.length - ? forkJoin( - createVariantsConfig.groups.map(c => { - return this.dataService.product.createProductOptionGroups({ - code: normalizeString(c.name, '-'), - translations: [{ languageCode, name: c.name }], - options: c.values.map(v => ({ - code: normalizeString(v, '-'), - translations: [{ languageCode, name: v }], - })), - }); - }), - ) - : of([]); + const createOptionGroups$ = this.createProductOptionGroups(nonEmptyOptionGroups, languageCode); return forkJoin(createProduct$, createOptionGroups$).pipe( - mergeMap(([{ createProduct }, createOptionGroups]) => { - const optionGroups = createOptionGroups.map(g => g.createProductOptionGroup); + mergeMap(([{ createProduct }, optionGroups]) => { const addOptionsToProduct$ = optionGroups.length ? forkJoin( optionGroups.map(optionGroup => { @@ -119,6 +104,25 @@ export class ProductDetailService { ); } + createProductOptionGroups(groups: Array<{ name: string; values: string[] }>, languageCode: LanguageCode) { + return groups.length + ? forkJoin( + groups.map(c => { + return this.dataService.product + .createProductOptionGroups({ + code: normalizeString(c.name, '-'), + translations: [{ languageCode, name: c.name }], + options: c.values.map(v => ({ + code: normalizeString(v, '-'), + translations: [{ languageCode, name: v }], + })), + }) + .pipe(map(data => data.createProductOptionGroup)); + }), + ) + : of([]); + } + createProductVariants( product: { name: string; id: string }, variantData: Array<{ price: number; sku: string; stock: number; optionIds: string[] }>, diff --git a/packages/admin-ui/src/i18n-messages/en.json b/packages/admin-ui/src/i18n-messages/en.json index 6835227f36..1dd586d973 100644 --- a/packages/admin-ui/src/i18n-messages/en.json +++ b/packages/admin-ui/src/i18n-messages/en.json @@ -30,6 +30,8 @@ "add-option": "Add option", "assets-selected-count": "{ count } assets selected", "collection-contents": "Collection contents", + "confirm-adding-options-delete-default-body": "Adding options to this product will cause the existing default variant to be deleted. Do you wish to proceed?", + "confirm-adding-options-delete-default-title": "Delete default variant?", "confirm-delete-collection": "Delete collection?", "confirm-delete-country": "Delete country?", "confirm-delete-facet": "Delete facet?", @@ -41,6 +43,8 @@ "create-new-facet": "Create new facet", "create-new-product": "New product", "created-new-variants-success": "Successfully created {count} new {count, plural, one {variant} other {variants}}", + "default-variant": "Default variant", + "delete-default-variant": "Delete default variant", "display-variant-cards": "View details", "display-variant-table": "View as table", "drop-files-to-upload": "Drop files to upload",