@vendure/admin-ui 1.6.4 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/bundles/vendure-admin-ui-catalog.umd.js +196 -20
  2. package/bundles/vendure-admin-ui-catalog.umd.js.map +1 -1
  3. package/bundles/vendure-admin-ui-core.umd.js +292 -323
  4. package/bundles/vendure-admin-ui-core.umd.js.map +1 -1
  5. package/bundles/vendure-admin-ui-customer.umd.js +39 -18
  6. package/bundles/vendure-admin-ui-customer.umd.js.map +1 -1
  7. package/bundles/vendure-admin-ui-order.umd.js +141 -119
  8. package/bundles/vendure-admin-ui-order.umd.js.map +1 -1
  9. package/catalog/components/generate-product-variants/generate-product-variants.component.d.ts +3 -3
  10. package/catalog/components/option-value-input/option-value-input.component.d.ts +20 -8
  11. package/catalog/components/product-variants-editor/product-variants-editor.component.d.ts +10 -3
  12. package/catalog/vendure-admin-ui-catalog.metadata.json +1 -1
  13. package/core/common/generated-types.d.ts +89 -19
  14. package/core/common/utilities/configurable-operation-utils.d.ts +4 -2
  15. package/core/common/version.d.ts +1 -1
  16. package/core/data/definitions/order-definitions.d.ts +2 -0
  17. package/core/data/definitions/product-definitions.d.ts +1 -0
  18. package/core/data/providers/order-data.service.d.ts +1 -0
  19. package/core/data/providers/product-data.service.d.ts +1 -0
  20. package/core/shared/components/custom-field-control/custom-field-control.component.d.ts +6 -2
  21. package/core/shared/components/data-table/data-table.component.d.ts +5 -2
  22. package/core/shared/dynamic-form-inputs/register-dynamic-input-components.d.ts +2 -1
  23. package/core/shared/dynamic-form-inputs/select-form-input/select-form-input.component.d.ts +10 -2
  24. package/core/shared/pipes/custom-field-label.pipe.d.ts +4 -10
  25. package/core/vendure-admin-ui-core.metadata.json +1 -1
  26. package/customer/components/customer-group-list/customer-group-list.component.d.ts +6 -4
  27. package/customer/vendure-admin-ui-customer.metadata.json +1 -1
  28. package/esm2015/catalog/components/generate-product-variants/generate-product-variants.component.js +12 -5
  29. package/esm2015/catalog/components/option-value-input/option-value-input.component.js +62 -12
  30. package/esm2015/catalog/components/product-variants-editor/product-variants-editor.component.js +109 -11
  31. package/esm2015/core/common/generated-types.js +2 -1
  32. package/esm2015/core/common/introspection-result.js +191 -255
  33. package/esm2015/core/common/utilities/configurable-operation-utils.js +11 -8
  34. package/esm2015/core/common/version.js +2 -2
  35. package/esm2015/core/components/app-shell/app-shell.component.js +1 -1
  36. package/esm2015/core/components/main-nav/main-nav.component.js +1 -1
  37. package/esm2015/core/data/definitions/order-definitions.js +39 -25
  38. package/esm2015/core/data/definitions/product-definitions.js +743 -735
  39. package/esm2015/core/data/providers/order-data.service.js +7 -2
  40. package/esm2015/core/data/providers/product-data.service.js +5 -2
  41. package/esm2015/core/shared/components/custom-field-control/custom-field-control.component.js +9 -3
  42. package/esm2015/core/shared/components/data-table/data-table.component.js +9 -2
  43. package/esm2015/core/shared/dynamic-form-inputs/select-form-input/select-form-input.component.js +15 -2
  44. package/esm2015/core/shared/pipes/custom-field-label.pipe.js +4 -19
  45. package/esm2015/customer/components/customer-group-list/customer-group-list.component.js +25 -12
  46. package/esm2015/order/components/fulfill-order-dialog/fulfill-order-dialog.component.js +3 -2
  47. package/esm2015/order/components/fulfillment-detail/fulfillment-detail.component.js +9 -18
  48. package/esm2015/order/components/line-fulfillment/line-fulfillment.component.js +10 -21
  49. package/esm2015/order/components/order-custom-fields-card/order-custom-fields-card.component.js +30 -4
  50. package/esm2015/order/components/order-detail/order-detail.component.js +49 -20
  51. package/esm2015/order/components/order-list/order-list.component.js +22 -15
  52. package/esm2015/order/components/order-payment-card/order-payment-card.component.js +2 -2
  53. package/esm2015/order/components/order-table/order-table.component.js +1 -1
  54. package/fesm2015/vendure-admin-ui-catalog.js +177 -22
  55. package/fesm2015/vendure-admin-ui-catalog.js.map +1 -1
  56. package/fesm2015/vendure-admin-ui-core.js +975 -995
  57. package/fesm2015/vendure-admin-ui-core.js.map +1 -1
  58. package/fesm2015/vendure-admin-ui-customer.js +23 -11
  59. package/fesm2015/vendure-admin-ui-customer.js.map +1 -1
  60. package/fesm2015/vendure-admin-ui-order.js +116 -75
  61. package/fesm2015/vendure-admin-ui-order.js.map +1 -1
  62. package/order/components/line-fulfillment/line-fulfillment.component.d.ts +2 -2
  63. package/order/components/modification-detail/modification-detail.component.d.ts +1 -1
  64. package/order/components/order-custom-fields-card/order-custom-fields-card.component.d.ts +4 -2
  65. package/order/components/order-list/order-list.component.d.ts +1 -0
  66. package/order/vendure-admin-ui-order.metadata.json +1 -1
  67. package/package.json +2 -2
  68. package/static/i18n-messages/cs.json +6 -2
  69. package/static/i18n-messages/de.json +6 -2
  70. package/static/i18n-messages/en.json +8 -3
  71. package/static/i18n-messages/es.json +6 -2
  72. package/static/i18n-messages/fr.json +6 -2
  73. package/static/i18n-messages/it.json +6 -2
  74. package/static/i18n-messages/pl.json +6 -2
  75. package/static/i18n-messages/pt_BR.json +6 -2
  76. package/static/i18n-messages/pt_PT.json +6 -2
  77. package/static/i18n-messages/ru.json +6 -2
  78. package/static/i18n-messages/uk.json +6 -2
  79. package/static/i18n-messages/zh_Hans.json +6 -2
  80. package/static/i18n-messages/zh_Hant.json +6 -2
  81. package/static/styles/_variables.scss +3 -0
  82. package/static/styles/global/_sass-overrides.scss +3 -0
  83. package/static/styles/global/_utilities.scss +1 -0
  84. package/static/styles/styles.scss +1 -0
  85. package/static/styles/ui-extension-theme.scss +1 -0
  86. package/static/theme.min.css +1 -1
@@ -73,4 +73,4 @@ OrderTableComponent.propDecorators = {
73
73
  order: [{ type: Input }],
74
74
  orderLineCustomFields: [{ type: Input }]
75
75
  };
76
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JkZXItdGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9vcmRlci9zcmMvY29tcG9uZW50cy9vcmRlci10YWJsZS9vcmRlci10YWJsZS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQVUsTUFBTSxlQUFlLENBQUM7QUFDbEYsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsY0FBYyxFQUFrQyxNQUFNLHdCQUF3QixDQUFDO0FBUXhGLE1BQU0sT0FBTyxtQkFBbUI7SUFOaEM7UUFTSSxpQ0FBNEIsR0FBRyxLQUFLLENBQUM7UUFDckMsd0JBQW1CLEdBRWYsRUFBRSxDQUFDO0lBa0VYLENBQUM7SUFoRUcsSUFBSSw0QkFBNEI7UUFDNUIsT0FBTyxJQUFJLENBQUMsNEJBQTRCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQy9FLENBQUM7SUFFRCxJQUFJLFVBQVU7UUFDVixPQUFPLENBQUMsSUFBSSxDQUFDLDRCQUE0QixJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxDQUFDO0lBQ3ZGLENBQUM7SUFFRCxRQUFRO1FBQ0osSUFBSSxDQUFDLDRCQUE0QixHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQzFFLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRCwyQkFBMkI7UUFDdkIsSUFBSSxDQUFDLDRCQUE0QixHQUFHLENBQUMsSUFBSSxDQUFDLDRCQUE0QixDQUFDO0lBQzNFLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxJQUF1QjtRQUNwQyxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDM0UsQ0FBQztJQUVPLG1CQUFtQjtRQUN2QixLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFO1lBQ2pDLE1BQU0sU0FBUyxHQUFHLElBQUksU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3BDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxxQkFBcUI7aUJBQ3BDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRTtnQkFDVixNQUFNLEtBQUssR0FBSSxJQUFZLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDdEQsU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLElBQUksV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7Z0JBQzFELE9BQU87b0JBQ0gsTUFBTTtvQkFDTixTQUFTO29CQUNULEtBQUs7aUJBQ1IsQ0FBQztZQUNOLENBQUMsQ0FBQztpQkFDRCxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQ1osT0FBTyxJQUFJLENBQUMsNEJBQTRCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUM7WUFDMUUsQ0FBQyxDQUFDLENBQUM7WUFDUCxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQztTQUM5QztJQUNMLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxTQUFnQztRQUM3QyxNQUFNLEVBQUUsR0FBRyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BELE9BQU8sQ0FBQyxZQUFZLEVBQUUsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRCwwQkFBMEIsQ0FDdEIsS0FBMkIsRUFDM0IsbUJBQTBDO1FBRTFDLE1BQU0sRUFBRSxHQUFHLG1CQUFtQixDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5RCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDMUQsSUFBSSxTQUFTLEVBQUU7WUFDWCxPQUFPLFNBQVMsQ0FBQyxVQUFVLElBQUksU0FBUyxDQUFDO1NBQzVDO0lBQ0wsQ0FBQztJQUVELGdCQUFnQixDQUFDLEtBQTJCO1FBQ3hDLElBQUksS0FBSyxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUU7WUFDNUIsT0FBTyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQy9GO2FBQU07WUFDSCxPQUFPLEVBQUUsQ0FBQztTQUNiO0lBQ0wsQ0FBQzs7O1lBN0VKLFNBQVMsU0FBQztnQkFDUCxRQUFRLEVBQUUsaUJBQWlCO2dCQUMzQixxaFBBQTJDO2dCQUUzQyxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTs7YUFDbEQ7OztvQkFFSSxLQUFLO29DQUNMLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBJbnB1dCwgT25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQ29udHJvbCwgRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQWRqdXN0bWVudFR5cGUsIEN1c3RvbUZpZWxkQ29uZmlnLCBPcmRlckRldGFpbCB9IGZyb20gJ0B2ZW5kdXJlL2FkbWluLXVpL2NvcmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ3Zkci1vcmRlci10YWJsZScsXG4gICAgdGVtcGxhdGVVcmw6ICcuL29yZGVyLXRhYmxlLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9vcmRlci10YWJsZS5jb21wb25lbnQuc2NzcyddLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBPcmRlclRhYmxlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgICBASW5wdXQoKSBvcmRlcjogT3JkZXJEZXRhaWwuRnJhZ21lbnQ7XG4gICAgQElucHV0KCkgb3JkZXJMaW5lQ3VzdG9tRmllbGRzOiBDdXN0b21GaWVsZENvbmZpZ1tdO1xuICAgIG9yZGVyTGluZUN1c3RvbUZpZWxkc1Zpc2libGUgPSBmYWxzZTtcbiAgICBjdXN0b21GaWVsZHNGb3JMaW5lOiB7XG4gICAgICAgIFtsaW5lSWQ6IHN0cmluZ106IEFycmF5PHsgY29uZmlnOiBDdXN0b21GaWVsZENvbmZpZzsgZm9ybUdyb3VwOiBGb3JtR3JvdXA7IHZhbHVlOiBhbnkgfT47XG4gICAgfSA9IHt9O1xuXG4gICAgZ2V0IHZpc2libGVPcmRlckxpbmVDdXN0b21GaWVsZHMoKTogQ3VzdG9tRmllbGRDb25maWdbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9yZGVyTGluZUN1c3RvbUZpZWxkc1Zpc2libGUgPyB0aGlzLm9yZGVyTGluZUN1c3RvbUZpZWxkcyA6IFtdO1xuICAgIH1cblxuICAgIGdldCBzaG93RWxpZGVkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gIXRoaXMub3JkZXJMaW5lQ3VzdG9tRmllbGRzVmlzaWJsZSAmJiAwIDwgdGhpcy5vcmRlckxpbmVDdXN0b21GaWVsZHMubGVuZ3RoO1xuICAgIH1cblxuICAgIG5nT25Jbml0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLm9yZGVyTGluZUN1c3RvbUZpZWxkc1Zpc2libGUgPSB0aGlzLm9yZGVyTGluZUN1c3RvbUZpZWxkcy5sZW5ndGggPCAyO1xuICAgICAgICB0aGlzLmdldExpbmVDdXN0b21GaWVsZHMoKTtcbiAgICB9XG5cbiAgICB0b2dnbGVPcmRlckxpbmVDdXN0b21GaWVsZHMoKSB7XG4gICAgICAgIHRoaXMub3JkZXJMaW5lQ3VzdG9tRmllbGRzVmlzaWJsZSA9ICF0aGlzLm9yZGVyTGluZUN1c3RvbUZpZWxkc1Zpc2libGU7XG4gICAgfVxuXG4gICAgZ2V0TGluZURpc2NvdW50cyhsaW5lOiBPcmRlckRldGFpbC5MaW5lcykge1xuICAgICAgICByZXR1cm4gbGluZS5kaXNjb3VudHMuZmlsdGVyKGEgPT4gYS50eXBlID09PSBBZGp1c3RtZW50VHlwZS5QUk9NT1RJT04pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0TGluZUN1c3RvbUZpZWxkcygpIHtcbiAgICAgICAgZm9yIChjb25zdCBsaW5lIG9mIHRoaXMub3JkZXIubGluZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGZvcm1Hcm91cCA9IG5ldyBGb3JtR3JvdXAoe30pO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5vcmRlckxpbmVDdXN0b21GaWVsZHNcbiAgICAgICAgICAgICAgICAubWFwKGNvbmZpZyA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gKGxpbmUgYXMgYW55KS5jdXN0b21GaWVsZHNbY29uZmlnLm5hbWVdO1xuICAgICAgICAgICAgICAgICAgICBmb3JtR3JvdXAuYWRkQ29udHJvbChjb25maWcubmFtZSwgbmV3IEZvcm1Db250cm9sKHZhbHVlKSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JtR3JvdXAsXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5maWx0ZXIoZmllbGQgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5vcmRlckxpbmVDdXN0b21GaWVsZHNWaXNpYmxlID8gdHJ1ZSA6IGZpZWxkLnZhbHVlICE9IG51bGw7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLmN1c3RvbUZpZWxkc0ZvckxpbmVbbGluZS5pZF0gPSByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRQcm9tb3Rpb25MaW5rKHByb21vdGlvbjogT3JkZXJEZXRhaWwuRGlzY291bnRzKTogYW55W10ge1xuICAgICAgICBjb25zdCBpZCA9IHByb21vdGlvbi5hZGp1c3RtZW50U291cmNlLnNwbGl0KCc6JylbMV07XG4gICAgICAgIHJldHVybiBbJy9tYXJrZXRpbmcnLCAncHJvbW90aW9ucycsIGlkXTtcbiAgICB9XG5cbiAgICBnZXRDb3Vwb25Db2RlRm9yQWRqdXN0bWVudChcbiAgICAgICAgb3JkZXI6IE9yZGVyRGV0YWlsLkZyYWdtZW50LFxuICAgICAgICBwcm9tb3Rpb25BZGp1c3RtZW50OiBPcmRlckRldGFpbC5EaXNjb3VudHMsXG4gICAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgY29uc3QgaWQgPSBwcm9tb3Rpb25BZGp1c3RtZW50LmFkanVzdG1lbnRTb3VyY2Uuc3BsaXQoJzonKVsxXTtcbiAgICAgICAgY29uc3QgcHJvbW90aW9uID0gb3JkZXIucHJvbW90aW9ucy5maW5kKHAgPT4gcC5pZCA9PT0gaWQpO1xuICAgICAgICBpZiAocHJvbW90aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJvbW90aW9uLmNvdXBvbkNvZGUgfHwgdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0U2hpcHBpbmdOYW1lcyhvcmRlcjogT3JkZXJEZXRhaWwuRnJhZ21lbnQpIHtcbiAgICAgICAgaWYgKG9yZGVyLnNoaXBwaW5nTGluZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gb3JkZXIuc2hpcHBpbmdMaW5lcy5tYXAoc2hpcHBpbmdMaW5lID0+IHNoaXBwaW5nTGluZS5zaGlwcGluZ01ldGhvZC5uYW1lKS5qb2luKCcsICcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9XG4gICAgfVxufVxuIl19
76
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JkZXItdGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9vcmRlci9zcmMvY29tcG9uZW50cy9vcmRlci10YWJsZS9vcmRlci10YWJsZS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQVUsTUFBTSxlQUFlLENBQUM7QUFDbEYsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsY0FBYyxFQUFrQyxNQUFNLHdCQUF3QixDQUFDO0FBUXhGLE1BQU0sT0FBTyxtQkFBbUI7SUFOaEM7UUFTSSxpQ0FBNEIsR0FBRyxLQUFLLENBQUM7UUFDckMsd0JBQW1CLEdBRWYsRUFBRSxDQUFDO0lBa0VYLENBQUM7SUFoRUcsSUFBSSw0QkFBNEI7UUFDNUIsT0FBTyxJQUFJLENBQUMsNEJBQTRCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQy9FLENBQUM7SUFFRCxJQUFJLFVBQVU7UUFDVixPQUFPLENBQUMsSUFBSSxDQUFDLDRCQUE0QixJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxDQUFDO0lBQ3ZGLENBQUM7SUFFRCxRQUFRO1FBQ0osSUFBSSxDQUFDLDRCQUE0QixHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQzFFLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRCwyQkFBMkI7UUFDdkIsSUFBSSxDQUFDLDRCQUE0QixHQUFHLENBQUMsSUFBSSxDQUFDLDRCQUE0QixDQUFDO0lBQzNFLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxJQUF1QjtRQUNwQyxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDM0UsQ0FBQztJQUVPLG1CQUFtQjtRQUN2QixLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFO1lBQ2pDLE1BQU0sU0FBUyxHQUFHLElBQUksU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3BDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxxQkFBcUI7aUJBQ3BDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRTtnQkFDVixNQUFNLEtBQUssR0FBSSxJQUFZLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDdEQsU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLElBQUksV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7Z0JBQzFELE9BQU87b0JBQ0gsTUFBTTtvQkFDTixTQUFTO29CQUNULEtBQUs7aUJBQ1IsQ0FBQztZQUNOLENBQUMsQ0FBQztpQkFDRCxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQ1osT0FBTyxJQUFJLENBQUMsNEJBQTRCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUM7WUFDMUUsQ0FBQyxDQUFDLENBQUM7WUFDUCxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQztTQUM5QztJQUNMLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxTQUFnQztRQUM3QyxNQUFNLEVBQUUsR0FBRyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BELE9BQU8sQ0FBQyxZQUFZLEVBQUUsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRCwwQkFBMEIsQ0FDdEIsS0FBMkIsRUFDM0IsbUJBQTBDO1FBRTFDLE1BQU0sRUFBRSxHQUFHLG1CQUFtQixDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5RCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDMUQsSUFBSSxTQUFTLEVBQUU7WUFDWCxPQUFPLFNBQVMsQ0FBQyxVQUFVLElBQUksU0FBUyxDQUFDO1NBQzVDO0lBQ0wsQ0FBQztJQUVELGdCQUFnQixDQUFDLEtBQTJCO1FBQ3hDLElBQUksS0FBSyxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUU7WUFDNUIsT0FBTyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQy9GO2FBQU07WUFDSCxPQUFPLEVBQUUsQ0FBQztTQUNiO0lBQ0wsQ0FBQzs7O1lBN0VKLFNBQVMsU0FBQztnQkFDUCxRQUFRLEVBQUUsaUJBQWlCO2dCQUMzQixxaFBBQTJDO2dCQUUzQyxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTs7YUFDbEQ7OztvQkFFSSxLQUFLO29DQUNMLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBJbnB1dCwgT25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IEFkanVzdG1lbnRUeXBlLCBDdXN0b21GaWVsZENvbmZpZywgT3JkZXJEZXRhaWwgfSBmcm9tICdAdmVuZHVyZS9hZG1pbi11aS9jb3JlJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICd2ZHItb3JkZXItdGFibGUnLFxyXG4gICAgdGVtcGxhdGVVcmw6ICcuL29yZGVyLXRhYmxlLmNvbXBvbmVudC5odG1sJyxcclxuICAgIHN0eWxlVXJsczogWycuL29yZGVyLXRhYmxlLmNvbXBvbmVudC5zY3NzJ10sXHJcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcclxufSlcclxuZXhwb3J0IGNsYXNzIE9yZGVyVGFibGVDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xyXG4gICAgQElucHV0KCkgb3JkZXI6IE9yZGVyRGV0YWlsLkZyYWdtZW50O1xyXG4gICAgQElucHV0KCkgb3JkZXJMaW5lQ3VzdG9tRmllbGRzOiBDdXN0b21GaWVsZENvbmZpZ1tdO1xyXG4gICAgb3JkZXJMaW5lQ3VzdG9tRmllbGRzVmlzaWJsZSA9IGZhbHNlO1xyXG4gICAgY3VzdG9tRmllbGRzRm9yTGluZToge1xyXG4gICAgICAgIFtsaW5lSWQ6IHN0cmluZ106IEFycmF5PHsgY29uZmlnOiBDdXN0b21GaWVsZENvbmZpZzsgZm9ybUdyb3VwOiBGb3JtR3JvdXA7IHZhbHVlOiBhbnkgfT47XHJcbiAgICB9ID0ge307XHJcblxyXG4gICAgZ2V0IHZpc2libGVPcmRlckxpbmVDdXN0b21GaWVsZHMoKTogQ3VzdG9tRmllbGRDb25maWdbXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMub3JkZXJMaW5lQ3VzdG9tRmllbGRzVmlzaWJsZSA/IHRoaXMub3JkZXJMaW5lQ3VzdG9tRmllbGRzIDogW107XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IHNob3dFbGlkZWQoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuICF0aGlzLm9yZGVyTGluZUN1c3RvbUZpZWxkc1Zpc2libGUgJiYgMCA8IHRoaXMub3JkZXJMaW5lQ3VzdG9tRmllbGRzLmxlbmd0aDtcclxuICAgIH1cclxuXHJcbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLm9yZGVyTGluZUN1c3RvbUZpZWxkc1Zpc2libGUgPSB0aGlzLm9yZGVyTGluZUN1c3RvbUZpZWxkcy5sZW5ndGggPCAyO1xyXG4gICAgICAgIHRoaXMuZ2V0TGluZUN1c3RvbUZpZWxkcygpO1xyXG4gICAgfVxyXG5cclxuICAgIHRvZ2dsZU9yZGVyTGluZUN1c3RvbUZpZWxkcygpIHtcclxuICAgICAgICB0aGlzLm9yZGVyTGluZUN1c3RvbUZpZWxkc1Zpc2libGUgPSAhdGhpcy5vcmRlckxpbmVDdXN0b21GaWVsZHNWaXNpYmxlO1xyXG4gICAgfVxyXG5cclxuICAgIGdldExpbmVEaXNjb3VudHMobGluZTogT3JkZXJEZXRhaWwuTGluZXMpIHtcclxuICAgICAgICByZXR1cm4gbGluZS5kaXNjb3VudHMuZmlsdGVyKGEgPT4gYS50eXBlID09PSBBZGp1c3RtZW50VHlwZS5QUk9NT1RJT04pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZ2V0TGluZUN1c3RvbUZpZWxkcygpIHtcclxuICAgICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgdGhpcy5vcmRlci5saW5lcykge1xyXG4gICAgICAgICAgICBjb25zdCBmb3JtR3JvdXAgPSBuZXcgRm9ybUdyb3VwKHt9KTtcclxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5vcmRlckxpbmVDdXN0b21GaWVsZHNcclxuICAgICAgICAgICAgICAgIC5tYXAoY29uZmlnID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IChsaW5lIGFzIGFueSkuY3VzdG9tRmllbGRzW2NvbmZpZy5uYW1lXTtcclxuICAgICAgICAgICAgICAgICAgICBmb3JtR3JvdXAuYWRkQ29udHJvbChjb25maWcubmFtZSwgbmV3IEZvcm1Db250cm9sKHZhbHVlKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlnLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JtR3JvdXAsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLFxyXG4gICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgLmZpbHRlcihmaWVsZCA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMub3JkZXJMaW5lQ3VzdG9tRmllbGRzVmlzaWJsZSA/IHRydWUgOiBmaWVsZC52YWx1ZSAhPSBudWxsO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHRoaXMuY3VzdG9tRmllbGRzRm9yTGluZVtsaW5lLmlkXSA9IHJlc3VsdDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0UHJvbW90aW9uTGluayhwcm9tb3Rpb246IE9yZGVyRGV0YWlsLkRpc2NvdW50cyk6IGFueVtdIHtcclxuICAgICAgICBjb25zdCBpZCA9IHByb21vdGlvbi5hZGp1c3RtZW50U291cmNlLnNwbGl0KCc6JylbMV07XHJcbiAgICAgICAgcmV0dXJuIFsnL21hcmtldGluZycsICdwcm9tb3Rpb25zJywgaWRdO1xyXG4gICAgfVxyXG5cclxuICAgIGdldENvdXBvbkNvZGVGb3JBZGp1c3RtZW50KFxyXG4gICAgICAgIG9yZGVyOiBPcmRlckRldGFpbC5GcmFnbWVudCxcclxuICAgICAgICBwcm9tb3Rpb25BZGp1c3RtZW50OiBPcmRlckRldGFpbC5EaXNjb3VudHMsXHJcbiAgICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xyXG4gICAgICAgIGNvbnN0IGlkID0gcHJvbW90aW9uQWRqdXN0bWVudC5hZGp1c3RtZW50U291cmNlLnNwbGl0KCc6JylbMV07XHJcbiAgICAgICAgY29uc3QgcHJvbW90aW9uID0gb3JkZXIucHJvbW90aW9ucy5maW5kKHAgPT4gcC5pZCA9PT0gaWQpO1xyXG4gICAgICAgIGlmIChwcm9tb3Rpb24pIHtcclxuICAgICAgICAgICAgcmV0dXJuIHByb21vdGlvbi5jb3Vwb25Db2RlIHx8IHVuZGVmaW5lZDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0U2hpcHBpbmdOYW1lcyhvcmRlcjogT3JkZXJEZXRhaWwuRnJhZ21lbnQpIHtcclxuICAgICAgICBpZiAob3JkZXIuc2hpcHBpbmdMaW5lcy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG9yZGVyLnNoaXBwaW5nTGluZXMubWFwKHNoaXBwaW5nTGluZSA9PiBzaGlwcGluZ0xpbmUuc2hpcHBpbmdNZXRob2QubmFtZSkuam9pbignLCAnKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gJyc7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiJdfQ==
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, Injectable, EventEmitter, Input, HostBinding, Output, ContentChild, TemplateRef, SkipSelf, Optional, forwardRef, NgModule } from '@angular/core';
2
+ import { Component, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, Injectable, EventEmitter, Input, HostBinding, Output, ContentChild, TemplateRef, SkipSelf, Optional, ViewChildren, ElementRef, forwardRef, NgModule } from '@angular/core';
3
3
  import * as i1 from '@angular/router';
4
4
  import { Router, ActivatedRoute, RouterModule } from '@angular/router';
5
5
  import * as i2 from '@vendure/admin-ui/core';
6
6
  import { BaseDetailComponent, ServerConfigService, NotificationService, DataService, BaseListComponent, SortOrder, LogicalOperator, DeletionResult, ModalService, Permission, unicodePatternValidator, findTranslation, getConfigArgValue, createUpdatedTranslatable, encodeConfigArgValue, LocalStorageService, FacetValueSelectorComponent, flattenFacetValues, JobState, JobQueueService, getDefaultUiLanguage, BaseEntityResolver, AssetType, createResolveData, CanDeactivateDetailGuard, detailBreadcrumb, AssetPickerDialogComponent, AssetPreviewDialogComponent, GlobalFlag, SharedModule } from '@vendure/admin-ui/core';
7
7
  import { marker } from '@biesbjerg/ngx-translate-extract-marker';
8
- import { map, debounceTime, takeUntil, finalize, switchMap, filter, take, mergeMap, shareReplay, distinctUntilChanged, tap, mapTo, startWith, skipUntil, skip, withLatestFrom, delay, catchError } from 'rxjs/operators';
8
+ import { map, debounceTime, takeUntil, finalize, switchMap, filter, take, mergeMap, shareReplay, distinctUntilChanged, tap, mapTo, startWith, skipUntil, skip, withLatestFrom, delay, defaultIfEmpty, catchError } from 'rxjs/operators';
9
9
  import { FormGroup, FormControl, FormBuilder, Validators, FormArray, NG_VALUE_ACCESSOR } from '@angular/forms';
10
10
  import { BehaviorSubject, combineLatest, EMPTY, Subject, merge, of, forkJoin, throwError, from } from 'rxjs';
11
11
  import { normalizeString } from '@vendure/common/lib/normalize-string';
@@ -2184,6 +2184,7 @@ class ProductVariantsEditorComponent {
2184
2184
  this.notificationService = notificationService;
2185
2185
  this.modalService = modalService;
2186
2186
  this.formValueChanged = false;
2187
+ this.optionsChanged = false;
2187
2188
  this.generatedVariants = [];
2188
2189
  }
2189
2190
  ngOnInit() {
@@ -2209,16 +2210,105 @@ class ProductVariantsEditorComponent {
2209
2210
  ? marker('catalog.default-variant')
2210
2211
  : variant.options.map(o => o.name).join(' ');
2211
2212
  }
2212
- addOption() {
2213
+ addOptionGroup() {
2213
2214
  this.optionGroups.push({
2214
2215
  isNew: true,
2216
+ locked: false,
2215
2217
  name: '',
2216
2218
  values: [],
2217
2219
  });
2220
+ this.optionsChanged = true;
2218
2221
  }
2219
- removeOption(optionGroup) {
2220
- this.optionGroups = this.optionGroups.filter(og => og !== optionGroup);
2222
+ removeOptionGroup(optionGroup) {
2223
+ const id = optionGroup.id;
2224
+ if (optionGroup.isNew) {
2225
+ this.optionGroups = this.optionGroups.filter(og => og !== optionGroup);
2226
+ this.generateVariants();
2227
+ this.optionsChanged = true;
2228
+ }
2229
+ else if (id) {
2230
+ this.modalService
2231
+ .dialog({
2232
+ title: marker('catalog.confirm-delete-product-option-group'),
2233
+ translationVars: { name: optionGroup.name },
2234
+ buttons: [
2235
+ { type: 'secondary', label: marker('common.cancel') },
2236
+ { type: 'danger', label: marker('common.delete'), returnValue: true },
2237
+ ],
2238
+ })
2239
+ .pipe(switchMap(val => {
2240
+ if (val) {
2241
+ return this.dataService.product.removeOptionGroupFromProduct({
2242
+ optionGroupId: id,
2243
+ productId: this.product.id,
2244
+ });
2245
+ }
2246
+ else {
2247
+ return EMPTY;
2248
+ }
2249
+ }))
2250
+ .subscribe(({ removeOptionGroupFromProduct }) => {
2251
+ var _a;
2252
+ if (removeOptionGroupFromProduct.__typename === 'Product') {
2253
+ this.notificationService.success(marker('common.notify-delete-success'), {
2254
+ entity: 'ProductOptionGroup',
2255
+ });
2256
+ this.initOptionsAndVariants();
2257
+ this.optionsChanged = true;
2258
+ }
2259
+ else if (removeOptionGroupFromProduct.__typename === 'ProductOptionInUseError') {
2260
+ this.notificationService.error((_a = removeOptionGroupFromProduct.message) !== null && _a !== void 0 ? _a : '');
2261
+ }
2262
+ });
2263
+ }
2264
+ }
2265
+ addOption(groupId, optionName) {
2266
+ var _a;
2267
+ (_a = this.optionGroups.find(g => g.id === groupId)) === null || _a === void 0 ? void 0 : _a.values.push({ name: optionName, locked: false });
2221
2268
  this.generateVariants();
2269
+ this.optionsChanged = true;
2270
+ }
2271
+ removeOption(groupId, { id, name }) {
2272
+ const optionGroup = this.optionGroups.find(g => g.id === groupId);
2273
+ if (optionGroup) {
2274
+ if (!id) {
2275
+ optionGroup.values = optionGroup.values.filter(v => v.name !== name);
2276
+ this.generateVariants();
2277
+ }
2278
+ else {
2279
+ this.modalService
2280
+ .dialog({
2281
+ title: marker('catalog.confirm-delete-product-option'),
2282
+ translationVars: { name },
2283
+ buttons: [
2284
+ { type: 'secondary', label: marker('common.cancel') },
2285
+ { type: 'danger', label: marker('common.delete'), returnValue: true },
2286
+ ],
2287
+ })
2288
+ .pipe(switchMap(val => {
2289
+ if (val) {
2290
+ return this.dataService.product.deleteProductOption(id);
2291
+ }
2292
+ else {
2293
+ return EMPTY;
2294
+ }
2295
+ }))
2296
+ .subscribe(({ deleteProductOption }) => {
2297
+ var _a;
2298
+ if (deleteProductOption.result === DeletionResult.DELETED) {
2299
+ this.notificationService.success(marker('common.notify-delete-success'), {
2300
+ entity: 'ProductOption',
2301
+ });
2302
+ optionGroup.values = optionGroup.values.filter(v => v.id !== id);
2303
+ this.generateVariants();
2304
+ this.optionsChanged = true;
2305
+ }
2306
+ else {
2307
+ this.notificationService.error((_a = deleteProductOption.message) !== null && _a !== void 0 ? _a : '');
2308
+ }
2309
+ });
2310
+ }
2311
+ }
2222
2312
  }
2223
2313
  generateVariants() {
2224
2314
  const groups = this.optionGroups.map(g => g.values);
@@ -2260,10 +2350,11 @@ class ProductVariantsEditorComponent {
2260
2350
  stock: 0,
2261
2351
  };
2262
2352
  }
2263
- deleteVariant(id) {
2353
+ deleteVariant(id, options) {
2264
2354
  this.modalService
2265
2355
  .dialog({
2266
2356
  title: marker('catalog.confirm-delete-product-variant'),
2357
+ translationVars: { name: options.map(o => o.name).join(' ') },
2267
2358
  buttons: [
2268
2359
  { type: 'secondary', label: marker('common.cancel') },
2269
2360
  { type: 'danger', label: marker('common.delete'), returnValue: true },
@@ -2298,12 +2389,14 @@ class ProductVariantsEditorComponent {
2298
2389
  count: variants.length,
2299
2390
  });
2300
2391
  this.initOptionsAndVariants();
2392
+ this.optionsChanged = false;
2301
2393
  },
2302
2394
  });
2303
2395
  }
2304
2396
  checkUniqueSkus() {
2305
2397
  const withDuplicateSkus = this.generatedVariants.filter((variant, index) => {
2306
- return this.generatedVariants.find(gv => gv.sku.trim() === variant.sku.trim() && gv !== variant);
2398
+ return (variant.enabled &&
2399
+ this.generatedVariants.find(gv => gv.sku.trim() === variant.sku.trim() && gv !== variant));
2307
2400
  });
2308
2401
  if (withDuplicateSkus.length) {
2309
2402
  return this.modalService
@@ -2386,7 +2479,7 @@ class ProductVariantsEditorComponent {
2386
2479
  return forkJoin(groupsIds.map(id => this.dataService.product
2387
2480
  .getProductOptionGroup(id)
2388
2481
  .mapSingle(data => data.productOptionGroup)
2389
- .pipe(filter(notNullOrUndefined))));
2482
+ .pipe(filter(notNullOrUndefined)))).pipe(defaultIfEmpty([]));
2390
2483
  }
2391
2484
  createNewProductVariants(groups) {
2392
2485
  const options = groups
@@ -2434,15 +2527,20 @@ class ProductVariantsEditorComponent {
2434
2527
  .mapSingle(({ product }) => product)
2435
2528
  .subscribe(p => {
2436
2529
  this.product = p;
2530
+ const allUsedOptionIds = p.variants.map(v => v.options.map(option => option.id)).flat();
2531
+ const allUsedOptionGroupIds = p.variants
2532
+ .map(v => v.options.map(option => option.groupId))
2533
+ .flat();
2437
2534
  this.optionGroups = p.optionGroups.map(og => {
2438
2535
  return {
2439
2536
  id: og.id,
2440
2537
  isNew: false,
2441
2538
  name: og.name,
2539
+ locked: allUsedOptionGroupIds.includes(og.id),
2442
2540
  values: og.options.map(o => ({
2443
2541
  id: o.id,
2444
2542
  name: o.name,
2445
- locked: true,
2543
+ locked: allUsedOptionIds.includes(o.id),
2446
2544
  })),
2447
2545
  };
2448
2546
  });
@@ -2465,7 +2563,7 @@ class ProductVariantsEditorComponent {
2465
2563
  ProductVariantsEditorComponent.decorators = [
2466
2564
  { type: Component, args: [{
2467
2565
  selector: 'vdr-product-variants-editor',
2468
- template: "<vdr-action-bar>\r\n <vdr-ab-right>\r\n <button\r\n class=\"btn btn-primary\"\r\n (click)=\"save()\"\r\n [disabled]=\"!formValueChanged || getVariantsToAdd().length === 0\"\r\n >\r\n {{ 'common.add-new-variants' | translate: { count: getVariantsToAdd().length } }}\r\n </button>\r\n </vdr-ab-right>\r\n</vdr-action-bar>\r\n\r\n<div *ngFor=\"let group of optionGroups\" class=\"option-groups\">\r\n <div class=\"name\">\r\n <label>{{ 'catalog.option' | translate }}</label>\r\n <input clrInput [(ngModel)]=\"group.name\" name=\"name\" [readonly]=\"!group.isNew\" />\r\n </div>\r\n <div class=\"values\">\r\n <label>{{ 'catalog.option-values' | translate }}</label>\r\n <vdr-option-value-input\r\n #optionValueInputComponent\r\n [(ngModel)]=\"group.values\"\r\n (ngModelChange)=\"generateVariants()\"\r\n [groupName]=\"group.name\"\r\n [disabled]=\"group.name === ''\"\r\n ></vdr-option-value-input>\r\n </div>\r\n <div>\r\n <button *ngIf=\"group.isNew\" class=\"btn btn-icon btn-danger-outline mt5\" (click)=\"removeOption(group)\">\r\n <clr-icon shape=\"trash\"></clr-icon>\r\n </button>\r\n </div>\r\n</div>\r\n<button\r\n class=\"btn btn-primary-outline btn-sm\"\r\n (click)=\"addOption()\"\r\n>\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.add-option' | translate }}\r\n</button>\r\n\r\n<div class=\"variants-preview\">\r\n <table class=\"table\">\r\n <thead>\r\n <tr>\r\n <th>{{ 'common.create' | translate }}</th>\r\n <th>{{ 'catalog.variant' | translate }}</th>\r\n <th>{{ 'catalog.sku' | translate }}</th>\r\n <th>{{ 'catalog.price' | translate }}</th>\r\n <th>{{ 'catalog.stock-on-hand' | translate }}</th>\r\n <th></th>\r\n </tr>\r\n </thead>\r\n <tr *ngFor=\"let variant of generatedVariants\" [class.disabled]=\"!variant.enabled || variant.existing\">\r\n <td>\r\n <input\r\n type=\"checkbox\"\r\n *ngIf=\"!variant.existing\"\r\n [(ngModel)]=\"variant.enabled\"\r\n name=\"enabled\"\r\n clrCheckbox\r\n (ngModelChange)=\"formValueChanged = true\"\r\n />\r\n </td>\r\n <td>\r\n {{ getVariantName(variant) | translate }}\r\n </td>\r\n <td>\r\n <clr-input-container *ngIf=\"!variant.existing\">\r\n <input\r\n clrInput\r\n type=\"text\"\r\n [(ngModel)]=\"variant.sku\"\r\n [placeholder]=\"'catalog.sku' | translate\"\r\n name=\"sku\"\r\n required\r\n (ngModelChange)=\"onFormChanged(variant)\"\r\n />\r\n </clr-input-container>\r\n <span *ngIf=\"variant.existing\">{{ variant.sku }}</span>\r\n </td>\r\n <td>\r\n <clr-input-container *ngIf=\"!variant.existing\">\r\n <vdr-currency-input\r\n clrInput\r\n [(ngModel)]=\"variant.price\"\r\n name=\"price\"\r\n [currencyCode]=\"currencyCode\"\r\n (ngModelChange)=\"onFormChanged(variant)\"\r\n ></vdr-currency-input>\r\n </clr-input-container>\r\n <span *ngIf=\"variant.existing\">{{ variant.price | localeCurrency: currencyCode }}</span>\r\n </td>\r\n <td>\r\n <clr-input-container *ngIf=\"!variant.existing\">\r\n <input\r\n clrInput\r\n type=\"number\"\r\n [(ngModel)]=\"variant.stock\"\r\n name=\"stock\"\r\n min=\"0\"\r\n step=\"1\"\r\n (ngModelChange)=\"onFormChanged(variant)\"\r\n />\r\n </clr-input-container>\r\n <span *ngIf=\"variant.existing\">{{ variant.stock }}</span>\r\n </td>\r\n <td>\r\n <vdr-dropdown *ngIf=\"variant.productVariantId as productVariantId\">\r\n <button class=\"icon-button\" vdrDropdownTrigger>\r\n <clr-icon shape=\"ellipsis-vertical\"></clr-icon>\r\n </button>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n <button\r\n type=\"button\"\r\n class=\"delete-button\"\r\n (click)=\"deleteVariant(productVariantId)\"\r\n vdrDropdownItem\r\n >\r\n <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon>\r\n {{ 'common.delete' | translate }}\r\n </button>\r\n </vdr-dropdown-menu>\r\n </vdr-dropdown>\r\n </td>\r\n </tr>\r\n </table>\r\n</div>\r\n",
2566
+ template: "<vdr-action-bar>\r\n <vdr-ab-right>\r\n <button\r\n class=\"btn btn-primary\"\r\n (click)=\"save()\"\r\n [disabled]=\"(!formValueChanged && !optionsChanged) || getVariantsToAdd().length === 0\"\r\n >\r\n {{ 'common.add-new-variants' | translate: { count: getVariantsToAdd().length } }}\r\n </button>\r\n </vdr-ab-right>\r\n</vdr-action-bar>\r\n\r\n<div *ngFor=\"let group of optionGroups\" class=\"option-groups\">\r\n <div class=\"name\">\r\n <label>{{ 'catalog.option' | translate }}</label>\r\n <input clrInput [(ngModel)]=\"group.name\" name=\"name\" [readonly]=\"!group.isNew\" />\r\n </div>\r\n <div class=\"values\">\r\n <label>{{ 'catalog.option-values' | translate }}</label>\r\n <vdr-option-value-input\r\n #optionValueInputComponent\r\n [options]=\"group.values\"\r\n [groupName]=\"group.name\"\r\n [disabled]=\"group.name === ''\"\r\n (add)=\"addOption(group.id, $event.name)\"\r\n (remove)=\"removeOption(group.id, $event)\"\r\n ></vdr-option-value-input>\r\n </div>\r\n <div>\r\n <button\r\n [disabled]=\"group.locked\"\r\n class=\"btn btn-icon btn-danger-outline mt5\" (click)=\"removeOptionGroup(group)\">\r\n <clr-icon shape=\"trash\"></clr-icon>\r\n </button>\r\n </div>\r\n</div>\r\n<button class=\"btn btn-primary-outline btn-sm\" (click)=\"addOptionGroup()\">\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.add-option' | translate }}\r\n</button>\r\n\r\n<div class=\"variants-preview\">\r\n <table class=\"table\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>{{ 'catalog.variant' | translate }}</th>\r\n <th>{{ 'catalog.sku' | translate }}</th>\r\n <th>{{ 'catalog.price' | translate }}</th>\r\n <th>{{ 'catalog.stock-on-hand' | translate }}</th>\r\n <th></th>\r\n </tr>\r\n </thead>\r\n <tr *ngFor=\"let variant of generatedVariants\" [class.disabled]=\"!variant.enabled || variant.existing\">\r\n <td class=\"left\">\r\n <clr-checkbox-wrapper *ngIf=\"!variant.existing\">\r\n <input\r\n type=\"checkbox\"\r\n [(ngModel)]=\"variant.enabled\"\r\n name=\"enabled\"\r\n clrCheckbox\r\n (ngModelChange)=\"formValueChanged = true\"\r\n />\r\n <label>{{ 'common.create' | translate }}</label>\r\n </clr-checkbox-wrapper>\r\n </td>\r\n <td>\r\n {{ getVariantName(variant) | translate }}\r\n </td>\r\n <td>\r\n <div class=\"flex center\">\r\n <clr-input-container *ngIf=\"!variant.existing\">\r\n <input\r\n clrInput\r\n type=\"text\"\r\n [(ngModel)]=\"variant.sku\"\r\n [placeholder]=\"'catalog.sku' | translate\"\r\n name=\"sku\"\r\n required\r\n (ngModelChange)=\"onFormChanged(variant)\"\r\n />\r\n </clr-input-container>\r\n <span *ngIf=\"variant.existing\">{{ variant.sku }}</span>\r\n </div>\r\n </td>\r\n <td>\r\n <div class=\"flex center\">\r\n <clr-input-container *ngIf=\"!variant.existing\">\r\n <vdr-currency-input\r\n clrInput\r\n [(ngModel)]=\"variant.price\"\r\n name=\"price\"\r\n [currencyCode]=\"currencyCode\"\r\n (ngModelChange)=\"onFormChanged(variant)\"\r\n ></vdr-currency-input>\r\n </clr-input-container>\r\n <span *ngIf=\"variant.existing\">{{ variant.price | localeCurrency: currencyCode }}</span>\r\n </div>\r\n </td>\r\n <td>\r\n <div class=\"flex center\">\r\n <clr-input-container *ngIf=\"!variant.existing\">\r\n <input\r\n clrInput\r\n type=\"number\"\r\n [(ngModel)]=\"variant.stock\"\r\n name=\"stock\"\r\n min=\"0\"\r\n step=\"1\"\r\n (ngModelChange)=\"onFormChanged(variant)\"\r\n />\r\n </clr-input-container>\r\n <span *ngIf=\"variant.existing\">{{ variant.stock }}</span>\r\n </div>\r\n </td>\r\n <td>\r\n <vdr-dropdown *ngIf=\"variant.productVariantId as productVariantId\">\r\n <button class=\"icon-button\" vdrDropdownTrigger>\r\n <clr-icon shape=\"ellipsis-vertical\"></clr-icon>\r\n </button>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n <button\r\n type=\"button\"\r\n class=\"delete-button\"\r\n (click)=\"deleteVariant(productVariantId, variant.options)\"\r\n vdrDropdownItem\r\n >\r\n <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon>\r\n {{ 'common.delete' | translate }}\r\n </button>\r\n </vdr-dropdown-menu>\r\n </vdr-dropdown>\r\n </td>\r\n </tr>\r\n </table>\r\n</div>\r\n",
2469
2567
  changeDetection: ChangeDetectionStrategy.Default,
2470
2568
  styles: [".option-groups{display:flex}.option-groups:first-of-type{margin-top:24px}.values{flex:1;margin:0 6px}.variants-preview tr.disabled td{background-color:var(--color-component-bg-100);color:var(--color-grey-400)}\n"]
2471
2569
  },] }
@@ -3240,6 +3338,12 @@ class GenerateProductVariantsComponent {
3240
3338
  }
3241
3339
  addOption() {
3242
3340
  this.optionGroups.push({ name: '', values: [] });
3341
+ const index = this.optionGroups.length - 1;
3342
+ setTimeout(() => {
3343
+ var _a;
3344
+ const input = (_a = this.groupNameInputs.get(index)) === null || _a === void 0 ? void 0 : _a.nativeElement;
3345
+ input === null || input === void 0 ? void 0 : input.focus();
3346
+ });
3243
3347
  }
3244
3348
  removeOption(name) {
3245
3349
  this.optionGroups = this.optionGroups.filter(g => g.name !== name);
@@ -3288,7 +3392,7 @@ class GenerateProductVariantsComponent {
3288
3392
  GenerateProductVariantsComponent.decorators = [
3289
3393
  { type: Component, args: [{
3290
3394
  selector: 'vdr-generate-product-variants',
3291
- template: "<div *ngFor=\"let group of optionGroups\" class=\"option-groups\">\r\n <div class=\"name\">\r\n <label>{{ 'catalog.option' | translate }}</label>\r\n <input\r\n placeholder=\"e.g. Size\"\r\n clrInput\r\n [(ngModel)]=\"group.name\"\r\n name=\"name\"\r\n required\r\n (keydown.enter)=\"handleEnter($event, optionValueInputComponent)\"\r\n />\r\n </div>\r\n <div class=\"values\">\r\n <label>{{ 'catalog.option-values' | translate }}</label>\r\n <vdr-option-value-input\r\n #optionValueInputComponent\r\n [(ngModel)]=\"group.values\"\r\n (ngModelChange)=\"generateVariants()\"\r\n [groupName]=\"group.name\"\r\n [disabled]=\"group.name === ''\"\r\n ></vdr-option-value-input>\r\n </div>\r\n <div class=\"remove-group\">\r\n <button\r\n class=\"btn btn-icon btn-warning-outline\"\r\n [title]=\"'catalog.remove-option' | translate\"\r\n (click)=\"removeOption(group.name)\"\r\n >\r\n <clr-icon shape=\"trash\"></clr-icon>\r\n </button>\r\n </div>\r\n</div>\r\n<button class=\"btn btn-primary-outline btn-sm\" (click)=\"addOption()\">\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.add-option' | translate }}\r\n</button>\r\n\r\n<div class=\"variants-preview\">\r\n <table class=\"table\">\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"1 < variants.length\">{{ 'common.create' | translate }}</th>\r\n <th *ngIf=\"1 < variants.length\">{{ 'catalog.variant' | translate }}</th>\r\n <th>{{ 'catalog.sku' | translate }}</th>\r\n <th>{{ 'catalog.price' | translate }}</th>\r\n <th>{{ 'catalog.stock-on-hand' | translate }}</th>\r\n </tr>\r\n </thead>\r\n <tr\r\n *ngFor=\"let variant of variants; trackBy: trackByFn\"\r\n [class.disabled]=\"!variantFormValues[variant.id].enabled\"\r\n >\r\n <td *ngIf=\"1 < variants.length\">\r\n <input\r\n type=\"checkbox\"\r\n (change)=\"onFormChange()\"\r\n [(ngModel)]=\"variantFormValues[variant.id].enabled\"\r\n clrCheckbox\r\n />\r\n </td>\r\n <td *ngIf=\"1 < variants.length\">\r\n {{ variant.values.join(' ') }}\r\n </td>\r\n <td>\r\n <clr-input-container>\r\n <input\r\n clrInput\r\n type=\"text\"\r\n (change)=\"onFormChange()\"\r\n [(ngModel)]=\"variantFormValues[variant.id].sku\"\r\n [placeholder]=\"'catalog.sku' | translate\"\r\n />\r\n </clr-input-container>\r\n </td>\r\n <td>\r\n <clr-input-container>\r\n <vdr-currency-input\r\n clrInput\r\n [(ngModel)]=\"variantFormValues[variant.id].price\"\r\n (ngModelChange)=\"onFormChange()\"\r\n [currencyCode]=\"currencyCode\"\r\n ></vdr-currency-input>\r\n </clr-input-container>\r\n </td>\r\n <td>\r\n <clr-input-container>\r\n <input\r\n clrInput\r\n type=\"number\"\r\n [(ngModel)]=\"variantFormValues[variant.id].stock\"\r\n (change)=\"onFormChange()\"\r\n min=\"0\"\r\n step=\"1\"\r\n />\r\n </clr-input-container>\r\n </td>\r\n </tr>\r\n </table>\r\n</div>\r\n",
3395
+ template: "<div *ngFor=\"let group of optionGroups\" class=\"option-groups\">\r\n <div class=\"name\">\r\n <label>{{ 'catalog.option' | translate }}</label>\r\n <input\r\n #optionGroupName\r\n placeholder=\"e.g. Size\"\r\n clrInput\r\n [(ngModel)]=\"group.name\"\r\n name=\"name\"\r\n required\r\n (keydown.enter)=\"handleEnter($event, optionValueInputComponent)\"\r\n />\r\n </div>\r\n <div class=\"values\">\r\n <label>{{ 'catalog.option-values' | translate }}</label>\r\n <vdr-option-value-input\r\n #optionValueInputComponent\r\n [(ngModel)]=\"group.values\"\r\n (ngModelChange)=\"generateVariants()\"\r\n (edit)=\"generateVariants()\"\r\n [groupName]=\"group.name\"\r\n [disabled]=\"group.name === ''\"\r\n ></vdr-option-value-input>\r\n </div>\r\n <div class=\"remove-group\">\r\n <button\r\n class=\"btn btn-icon btn-warning-outline\"\r\n [title]=\"'catalog.remove-option' | translate\"\r\n (click)=\"removeOption(group.name)\"\r\n >\r\n <clr-icon shape=\"trash\"></clr-icon>\r\n </button>\r\n </div>\r\n</div>\r\n<button class=\"btn btn-primary-outline btn-sm\" (click)=\"addOption()\">\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.add-option' | translate }}\r\n</button>\r\n\r\n<div class=\"variants-preview\">\r\n <table class=\"table\">\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"1 < variants.length\">{{ 'common.create' | translate }}</th>\r\n <th *ngIf=\"1 < variants.length\">{{ 'catalog.variant' | translate }}</th>\r\n <th>{{ 'catalog.sku' | translate }}</th>\r\n <th>{{ 'catalog.price' | translate }}</th>\r\n <th>{{ 'catalog.stock-on-hand' | translate }}</th>\r\n </tr>\r\n </thead>\r\n <tr\r\n *ngFor=\"let variant of variants; trackBy: trackByFn\"\r\n [class.disabled]=\"!variantFormValues[variant.id].enabled\"\r\n >\r\n <td *ngIf=\"1 < variants.length\">\r\n <input\r\n type=\"checkbox\"\r\n (change)=\"onFormChange()\"\r\n [(ngModel)]=\"variantFormValues[variant.id].enabled\"\r\n clrCheckbox\r\n />\r\n </td>\r\n <td *ngIf=\"1 < variants.length\">\r\n {{ variant.values.join(' ') }}\r\n </td>\r\n <td>\r\n <clr-input-container>\r\n <input\r\n clrInput\r\n type=\"text\"\r\n (change)=\"onFormChange()\"\r\n [(ngModel)]=\"variantFormValues[variant.id].sku\"\r\n [placeholder]=\"'catalog.sku' | translate\"\r\n />\r\n </clr-input-container>\r\n </td>\r\n <td>\r\n <clr-input-container>\r\n <vdr-currency-input\r\n clrInput\r\n [(ngModel)]=\"variantFormValues[variant.id].price\"\r\n (ngModelChange)=\"onFormChange()\"\r\n [currencyCode]=\"currencyCode\"\r\n ></vdr-currency-input>\r\n </clr-input-container>\r\n </td>\r\n <td>\r\n <clr-input-container>\r\n <input\r\n clrInput\r\n type=\"number\"\r\n [(ngModel)]=\"variantFormValues[variant.id].stock\"\r\n (change)=\"onFormChange()\"\r\n min=\"0\"\r\n step=\"1\"\r\n />\r\n </clr-input-container>\r\n </td>\r\n </tr>\r\n </table>\r\n</div>\r\n",
3292
3396
  styles: [":host{display:block;margin-bottom:120px}.option-groups{display:flex}.values{flex:1;margin:0 6px}.remove-group{padding-top:18px}.variants-preview tr.disabled td{background-color:var(--color-component-bg-100);color:var(--color-grey-400)}\n"]
3293
3397
  },] }
3294
3398
  ];
@@ -3296,7 +3400,8 @@ GenerateProductVariantsComponent.ctorParameters = () => [
3296
3400
  { type: DataService }
3297
3401
  ];
3298
3402
  GenerateProductVariantsComponent.propDecorators = {
3299
- variantsChange: [{ type: Output }]
3403
+ variantsChange: [{ type: Output }],
3404
+ groupNameInputs: [{ type: ViewChildren, args: ['optionGroupName', { read: ElementRef },] }]
3300
3405
  };
3301
3406
 
3302
3407
  const OPTION_VALUE_INPUT_VALUE_ACCESSOR = {
@@ -3308,10 +3413,18 @@ class OptionValueInputComponent {
3308
3413
  constructor(changeDetector) {
3309
3414
  this.changeDetector = changeDetector;
3310
3415
  this.groupName = '';
3416
+ this.add = new EventEmitter();
3417
+ this.remove = new EventEmitter();
3418
+ this.edit = new EventEmitter();
3311
3419
  this.disabled = false;
3312
3420
  this.input = '';
3313
3421
  this.isFocussed = false;
3314
3422
  this.lastSelected = false;
3423
+ this.editingIndex = -1;
3424
+ }
3425
+ get optionValues() {
3426
+ var _a, _b;
3427
+ return (_b = (_a = this.formValue) !== null && _a !== void 0 ? _a : this.options) !== null && _b !== void 0 ? _b : [];
3315
3428
  }
3316
3429
  registerOnChange(fn) {
3317
3430
  this.onChangeFn = fn;
@@ -3324,15 +3437,42 @@ class OptionValueInputComponent {
3324
3437
  this.changeDetector.markForCheck();
3325
3438
  }
3326
3439
  writeValue(obj) {
3327
- this.options = obj || [];
3440
+ this.formValue = obj || [];
3328
3441
  }
3329
3442
  focus() {
3330
3443
  this.textArea.nativeElement.focus();
3331
3444
  }
3445
+ editName(index, event) {
3446
+ var _a;
3447
+ const optionValue = this.optionValues[index];
3448
+ if (!optionValue.locked && !optionValue.id) {
3449
+ event.cancelBubble = true;
3450
+ this.editingIndex = index;
3451
+ const input = (_a = this.nameInputs.get(index)) === null || _a === void 0 ? void 0 : _a.nativeElement;
3452
+ setTimeout(() => input === null || input === void 0 ? void 0 : input.focus());
3453
+ }
3454
+ }
3455
+ updateOption(index, event) {
3456
+ const optionValue = this.optionValues[index];
3457
+ const newName = event.target.value;
3458
+ if (optionValue) {
3459
+ if (newName) {
3460
+ optionValue.name = newName;
3461
+ this.edit.emit({ index, option: optionValue });
3462
+ }
3463
+ this.editingIndex = -1;
3464
+ }
3465
+ }
3332
3466
  removeOption(option) {
3467
+ var _a;
3333
3468
  if (!option.locked) {
3334
- this.options = this.options.filter(o => o.name !== option.name);
3335
- this.onChangeFn(this.options);
3469
+ if (this.formValue) {
3470
+ this.formValue = (_a = this.formValue) === null || _a === void 0 ? void 0 : _a.filter(o => o.name !== option.name);
3471
+ this.onChangeFn(this.formValue);
3472
+ }
3473
+ else {
3474
+ this.remove.emit(option);
3475
+ }
3336
3476
  }
3337
3477
  }
3338
3478
  handleKey(event) {
@@ -3360,9 +3500,17 @@ class OptionValueInputComponent {
3360
3500
  this.addOptionValue();
3361
3501
  }
3362
3502
  addOptionValue() {
3363
- this.options = unique([...this.options, ...this.parseInputIntoOptions(this.input)]);
3503
+ const options = this.parseInputIntoOptions(this.input);
3504
+ if (!this.formValue && this.options) {
3505
+ for (const option of options) {
3506
+ this.add.emit(option);
3507
+ }
3508
+ }
3509
+ else {
3510
+ this.formValue = unique([...this.formValue, ...options]);
3511
+ this.onChangeFn(this.formValue);
3512
+ }
3364
3513
  this.input = '';
3365
- this.onChangeFn(this.options);
3366
3514
  }
3367
3515
  parseInputIntoOptions(input) {
3368
3516
  return input
@@ -3372,18 +3520,19 @@ class OptionValueInputComponent {
3372
3520
  .map(s => ({ name: s, locked: false }));
3373
3521
  }
3374
3522
  removeLastOption() {
3375
- if (!this.options[this.options.length - 1].locked) {
3376
- this.options = this.options.slice(0, this.options.length - 1);
3523
+ if (this.optionValues.length) {
3524
+ const option = this.optionValues[this.optionValues.length - 1];
3525
+ this.removeOption(option);
3377
3526
  }
3378
3527
  }
3379
3528
  }
3380
3529
  OptionValueInputComponent.decorators = [
3381
3530
  { type: Component, args: [{
3382
3531
  selector: 'vdr-option-value-input',
3383
- template: "<div class=\"input-wrapper\" [class.focus]=\"isFocussed\" (click)=\"textArea.focus()\">\r\n <div class=\"chips\" *ngIf=\"0 < options.length\">\r\n <vdr-chip\r\n *ngFor=\"let option of options; last as isLast\"\r\n [icon]=\"option.locked ? 'lock' : 'times'\"\r\n [class.selected]=\"isLast && lastSelected\"\r\n [class.locked]=\"option.locked\"\r\n [colorFrom]=\"groupName\"\r\n (iconClick)=\"removeOption(option)\"\r\n >\r\n {{ option.name }}\r\n </vdr-chip>\r\n </div>\r\n <textarea\r\n #textArea\r\n (keyup)=\"handleKey($event)\"\r\n (focus)=\"isFocussed = true\"\r\n (blur)=\"handleBlur()\"\r\n [(ngModel)]=\"input\"\r\n [disabled]=\"disabled\"\r\n ></textarea>\r\n</div>\r\n",
3532
+ template: "<div class=\"input-wrapper\" [class.focus]=\"isFocussed\" (click)=\"textArea.focus()\">\r\n <div class=\"chips\" *ngIf=\"0 < optionValues.length\">\r\n <vdr-chip\r\n *ngFor=\"let option of optionValues; last as isLast; index as i\"\r\n [icon]=\"option.locked ? 'lock' : 'times'\"\r\n [class.selected]=\"isLast && lastSelected\"\r\n [class.locked]=\"option.locked\"\r\n [colorFrom]=\"groupName\"\r\n (iconClick)=\"removeOption(option)\"\r\n >\r\n <span [hidden]=\"editingIndex !== i\">\r\n <input\r\n #editNameInput\r\n type=\"text\"\r\n [ngModel]=\"option.name\"\r\n (blur)=\"updateOption(i, $event)\"\r\n (click)=\"$event.cancelBubble = true\"\r\n />\r\n </span>\r\n <span\r\n class=\"option-name\"\r\n [class.editable]=\"!option.locked && !option.id\"\r\n (click)=\"editName(i, $event)\" [hidden]=\"editingIndex === i\">{{ option.name }}</span>\r\n </vdr-chip>\r\n </div>\r\n <textarea\r\n #textArea\r\n (keyup)=\"handleKey($event)\"\r\n (focus)=\"isFocussed = true\"\r\n (blur)=\"handleBlur()\"\r\n [(ngModel)]=\"input\"\r\n [disabled]=\"disabled\"\r\n ></textarea>\r\n</div>\r\n",
3384
3533
  changeDetection: ChangeDetectionStrategy.Default,
3385
3534
  providers: [OPTION_VALUE_INPUT_VALUE_ACCESSOR],
3386
- styles: [".input-wrapper{background-color:#fff;border-radius:3px!important;border:1px solid var(--color-grey-300)!important;cursor:text}.input-wrapper.focus{border-color:var(--color-primary-500)!important;box-shadow:0 0 1px 1px var(--color-primary-100)}.input-wrapper .chips{padding:5px}.input-wrapper textarea{border:none;width:100%;height:24px;margin-top:3px;padding:0 6px}.input-wrapper textarea:focus{outline:none}.input-wrapper textarea:disabled{background-color:var(--color-component-bg-100)}vdr-chip ::ng-deep .wrapper{margin:0 3px}vdr-chip.locked{opacity:.8}vdr-chip.selected ::ng-deep .wrapper{border-color:var(--color-warning-500)!important;box-shadow:0 0 1px 1px var(--color-warning-400);opacity:.6}\n"]
3535
+ styles: [".input-wrapper{background-color:#fff;border-radius:3px!important;border:1px solid var(--color-grey-300)!important;cursor:text}.input-wrapper.focus{border-color:var(--color-primary-500)!important;box-shadow:0 0 1px 1px var(--color-primary-100)}.input-wrapper .chips{padding:5px}.input-wrapper textarea{border:none;width:100%;height:24px;margin-top:3px;padding:0 6px}.input-wrapper textarea:focus{outline:none}.input-wrapper textarea:disabled{background-color:var(--color-component-bg-100)}vdr-chip ::ng-deep .wrapper{margin:0 3px}vdr-chip.locked{opacity:.8}vdr-chip.selected ::ng-deep .wrapper{border-color:var(--color-warning-500)!important;box-shadow:0 0 1px 1px var(--color-warning-400);opacity:.6}vdr-chip .option-name.editable:hover{outline:1px solid var(--color-component-bg-300);outline-offset:1px;border-radius:1px}vdr-chip input{padding:0!important;margin-top:-2px;margin-bottom:-2px}\n"]
3387
3536
  },] }
3388
3537
  ];
3389
3538
  OptionValueInputComponent.ctorParameters = () => [
@@ -3391,7 +3540,13 @@ OptionValueInputComponent.ctorParameters = () => [
3391
3540
  ];
3392
3541
  OptionValueInputComponent.propDecorators = {
3393
3542
  groupName: [{ type: Input }],
3394
- textArea: [{ type: ViewChild, args: ['textArea', { static: true },] }]
3543
+ textArea: [{ type: ViewChild, args: ['textArea', { static: true },] }],
3544
+ nameInputs: [{ type: ViewChildren, args: ['editNameInput', { read: ElementRef },] }],
3545
+ options: [{ type: Input }],
3546
+ add: [{ type: Output }],
3547
+ remove: [{ type: Output }],
3548
+ edit: [{ type: Output }],
3549
+ disabled: [{ type: Input }]
3395
3550
  };
3396
3551
 
3397
3552
  class UpdateProductOptionDialogComponent {