@vendure/admin-ui 1.4.6 → 1.5.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 (117) hide show
  1. package/bundles/vendure-admin-ui-catalog.umd.js +186 -155
  2. package/bundles/vendure-admin-ui-catalog.umd.js.map +1 -1
  3. package/bundles/vendure-admin-ui-core.umd.js +350 -273
  4. package/bundles/vendure-admin-ui-core.umd.js.map +1 -1
  5. package/bundles/vendure-admin-ui-customer.umd.js +51 -20
  6. package/bundles/vendure-admin-ui-customer.umd.js.map +1 -1
  7. package/bundles/vendure-admin-ui-order.umd.js +107 -17
  8. package/bundles/vendure-admin-ui-order.umd.js.map +1 -1
  9. package/bundles/vendure-admin-ui-settings.umd.js +1 -1
  10. package/bundles/vendure-admin-ui-settings.umd.js.map +1 -1
  11. package/bundles/vendure-admin-ui-system.umd.js.map +1 -1
  12. package/catalog/components/{product-assets/product-assets.component.d.ts → assets/assets.component.d.ts} +4 -10
  13. package/catalog/components/facet-detail/facet-detail.component.d.ts +7 -2
  14. package/catalog/components/product-detail/product-detail.component.d.ts +2 -1
  15. package/catalog/components/product-variants-list/product-variants-list.component.d.ts +2 -1
  16. package/catalog/public_api.d.ts +1 -1
  17. package/catalog/vendure-admin-ui-catalog.metadata.json +1 -1
  18. package/core/common/generated-types.d.ts +115 -12
  19. package/core/common/version.d.ts +1 -1
  20. package/core/data/definitions/customer-definitions.d.ts +1 -0
  21. package/core/data/providers/customer-data.service.d.ts +1 -0
  22. package/core/data/providers/promotion-data.service.d.ts +2 -2
  23. package/core/data/utils/remove-readonly-custom-fields.d.ts +12 -3
  24. package/core/public_api.d.ts +2 -0
  25. package/core/shared/components/asset-preview-links/asset-preview-links.component.d.ts +5 -0
  26. package/core/shared/components/object-tree/object-tree.component.d.ts +3 -3
  27. package/core/shared/directives/if-default-channel-active.directive.d.ts +1 -1
  28. package/core/shared/directives/if-multichannel.directive.d.ts +1 -1
  29. package/core/shared/dynamic-form-inputs/relation-form-input/generic/relation-generic-input.component.d.ts +15 -0
  30. package/core/vendure-admin-ui-core.metadata.json +1 -1
  31. package/customer/components/address-card/address-card.component.d.ts +2 -0
  32. package/customer/components/customer-detail/customer-detail.component.d.ts +2 -0
  33. package/customer/components/customer-list/customer-list.component.d.ts +1 -2
  34. package/customer/vendure-admin-ui-customer.metadata.json +1 -1
  35. package/esm2015/catalog/catalog.module.js +3 -3
  36. package/esm2015/catalog/components/assets/assets.component.js +93 -0
  37. package/esm2015/catalog/components/collection-detail/collection-detail.component.js +2 -2
  38. package/esm2015/catalog/components/facet-detail/facet-detail.component.js +45 -17
  39. package/esm2015/catalog/components/product-detail/product-detail.component.js +4 -3
  40. package/esm2015/catalog/components/product-variants-list/product-variants-list.component.js +9 -2
  41. package/esm2015/catalog/public_api.js +2 -2
  42. package/esm2015/core/common/generated-types.js +30 -1
  43. package/esm2015/core/common/introspection-result.js +189 -249
  44. package/esm2015/core/common/utilities/configurable-operation-utils.js +1 -1
  45. package/esm2015/core/common/utilities/create-updated-translatable.js +1 -1
  46. package/esm2015/core/common/version.js +2 -2
  47. package/esm2015/core/data/definitions/customer-definitions.js +8 -1
  48. package/esm2015/core/data/definitions/order-definitions.js +2 -1
  49. package/esm2015/core/data/providers/customer-data.service.js +5 -2
  50. package/esm2015/core/data/providers/interceptor.js +1 -1
  51. package/esm2015/core/data/providers/promotion-data.service.js +3 -2
  52. package/esm2015/core/data/providers/shipping-method-data.service.js +1 -1
  53. package/esm2015/core/data/utils/remove-readonly-custom-fields.js +15 -3
  54. package/esm2015/core/public_api.js +3 -1
  55. package/esm2015/core/shared/components/address-form/address-form.component.js +1 -1
  56. package/esm2015/core/shared/components/asset-gallery/asset-gallery.component.js +2 -2
  57. package/esm2015/core/shared/components/asset-preview/asset-preview.component.js +3 -3
  58. package/esm2015/core/shared/components/asset-preview-links/asset-preview-links.component.js +18 -0
  59. package/esm2015/core/shared/components/object-tree/object-tree.component.js +3 -3
  60. package/esm2015/core/shared/components/tabbed-custom-fields/tabbed-custom-fields.component.js +3 -2
  61. package/esm2015/core/shared/directives/if-default-channel-active.directive.js +2 -2
  62. package/esm2015/core/shared/directives/if-multichannel.directive.js +2 -2
  63. package/esm2015/core/shared/dynamic-form-inputs/relation-form-input/generic/relation-generic-input.component.js +48 -0
  64. package/esm2015/core/shared/dynamic-form-inputs/relation-form-input/relation-form-input.component.js +2 -2
  65. package/esm2015/core/shared/shared.module.js +5 -1
  66. package/esm2015/customer/components/address-card/address-card.component.js +9 -3
  67. package/esm2015/customer/components/customer-detail/customer-detail.component.js +35 -13
  68. package/esm2015/customer/components/customer-list/customer-list.component.js +12 -9
  69. package/esm2015/order/components/add-manual-payment-dialog/add-manual-payment-dialog.component.js +1 -1
  70. package/esm2015/order/components/cancel-order-dialog/cancel-order-dialog.component.js +36 -6
  71. package/esm2015/order/components/fulfill-order-dialog/fulfill-order-dialog.component.js +1 -1
  72. package/esm2015/order/components/line-refunds/line-refunds.component.js +1 -1
  73. package/esm2015/order/components/modification-detail/modification-detail.component.js +1 -1
  74. package/esm2015/order/components/order-detail/order-detail.component.js +2 -2
  75. package/esm2015/order/components/order-editor/order-editor.component.js +22 -7
  76. package/esm2015/order/components/order-edits-preview-dialog/order-edits-preview-dialog.component.js +1 -1
  77. package/esm2015/order/components/order-history/order-history.component.js +2 -2
  78. package/esm2015/order/components/order-list/order-list.component.js +1 -1
  79. package/esm2015/order/components/order-table/order-table.component.js +2 -2
  80. package/esm2015/order/components/refund-order-dialog/refund-order-dialog.component.js +10 -5
  81. package/esm2015/order/order.routes.js +1 -1
  82. package/esm2015/settings/components/channel-list/channel-list.component.js +2 -2
  83. package/esm2015/settings/components/role-list/role-list.component.js +1 -1
  84. package/esm2015/settings/components/test-order-builder/test-order-builder.component.js +1 -1
  85. package/esm2015/settings/providers/routing/shipping-method-resolver.js +1 -1
  86. package/esm2015/system/components/job-list/job-list.component.js +1 -1
  87. package/fesm2015/vendure-admin-ui-catalog.js +147 -125
  88. package/fesm2015/vendure-admin-ui-catalog.js.map +1 -1
  89. package/fesm2015/vendure-admin-ui-core.js +308 -251
  90. package/fesm2015/vendure-admin-ui-core.js.map +1 -1
  91. package/fesm2015/vendure-admin-ui-customer.js +53 -22
  92. package/fesm2015/vendure-admin-ui-customer.js.map +1 -1
  93. package/fesm2015/vendure-admin-ui-order.js +67 -17
  94. package/fesm2015/vendure-admin-ui-order.js.map +1 -1
  95. package/fesm2015/vendure-admin-ui-settings.js +1 -1
  96. package/fesm2015/vendure-admin-ui-settings.js.map +1 -1
  97. package/fesm2015/vendure-admin-ui-system.js.map +1 -1
  98. package/order/components/cancel-order-dialog/cancel-order-dialog.component.d.ts +3 -0
  99. package/order/components/order-editor/order-editor.component.d.ts +8 -2
  100. package/order/vendure-admin-ui-order.metadata.json +1 -1
  101. package/package.json +11 -11
  102. package/settings/vendure-admin-ui-settings.metadata.json +1 -1
  103. package/static/i18n-messages/cs.json +7 -1
  104. package/static/i18n-messages/de.json +7 -1
  105. package/static/i18n-messages/en.json +9 -3
  106. package/static/i18n-messages/es.json +7 -1
  107. package/static/i18n-messages/fr.json +7 -1
  108. package/static/i18n-messages/it.json +7 -1
  109. package/static/i18n-messages/pl.json +7 -1
  110. package/static/i18n-messages/pt_BR.json +7 -1
  111. package/static/i18n-messages/pt_PT.json +7 -1
  112. package/static/i18n-messages/ru.json +7 -1
  113. package/static/i18n-messages/uk.json +7 -1
  114. package/static/i18n-messages/zh_Hans.json +7 -1
  115. package/static/i18n-messages/zh_Hant.json +7 -1
  116. package/static/vendure-ui-config.json +25 -10
  117. package/esm2015/catalog/components/product-assets/product-assets.component.js +0 -108
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/router'), require('@vendure/admin-ui/core'), require('@biesbjerg/ngx-translate-extract-marker'), require('rxjs/operators'), require('@angular/forms'), require('rxjs'), require('@vendure/common/lib/normalize-string'), require('@vendure/common/lib/shared-utils'), require('@vendure/common/lib/generated-shop-types'), require('@angular/common'), require('@vendure/common/lib/shared-constants'), require('@vendure/common/lib/unique'), require('@vendure/common/lib/pick'), require('@angular/cdk/drag-drop'), require('@angular/cdk/overlay'), require('@ng-select/ng-select')) :
3
- typeof define === 'function' && define.amd ? define('@vendure/admin-ui/catalog', ['exports', '@angular/core', '@angular/router', '@vendure/admin-ui/core', '@biesbjerg/ngx-translate-extract-marker', 'rxjs/operators', '@angular/forms', 'rxjs', '@vendure/common/lib/normalize-string', '@vendure/common/lib/shared-utils', '@vendure/common/lib/generated-shop-types', '@angular/common', '@vendure/common/lib/shared-constants', '@vendure/common/lib/unique', '@vendure/common/lib/pick', '@angular/cdk/drag-drop', '@angular/cdk/overlay', '@ng-select/ng-select'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.vendure = global.vendure || {}, global.vendure['admin-ui'] = global.vendure['admin-ui'] || {}, global.vendure['admin-ui'].catalog = {}), global.ng.core, global.ng.router, global.vendure['admin-ui'].core, global.ngxTranslateExtractMarker, global.rxjs.operators, global.ng.forms, global.rxjs, global.normalizeString, global.sharedUtils, global.generatedShopTypes, global.ng.common, global.sharedConstants, global.unique, global.pick, global.ng.cdk.dragDrop, global.ng.cdk.overlay, global.ngSelect));
5
- }(this, (function (exports, i0, i1, i2, ngxTranslateExtractMarker, operators, forms, rxjs, normalizeString, sharedUtils, generatedShopTypes, common, sharedConstants, unique, pick, dragDrop, overlay, ngSelect) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/router'), require('@vendure/admin-ui/core'), require('@biesbjerg/ngx-translate-extract-marker'), require('rxjs/operators'), require('@angular/forms'), require('rxjs'), require('@vendure/common/lib/normalize-string'), require('@vendure/common/lib/shared-utils'), require('@vendure/common/lib/generated-shop-types'), require('@angular/common'), require('@vendure/common/lib/shared-constants'), require('@vendure/common/lib/unique'), require('@vendure/common/lib/pick'), require('@angular/cdk/drag-drop'), require('@ng-select/ng-select')) :
3
+ typeof define === 'function' && define.amd ? define('@vendure/admin-ui/catalog', ['exports', '@angular/core', '@angular/router', '@vendure/admin-ui/core', '@biesbjerg/ngx-translate-extract-marker', 'rxjs/operators', '@angular/forms', 'rxjs', '@vendure/common/lib/normalize-string', '@vendure/common/lib/shared-utils', '@vendure/common/lib/generated-shop-types', '@angular/common', '@vendure/common/lib/shared-constants', '@vendure/common/lib/unique', '@vendure/common/lib/pick', '@angular/cdk/drag-drop', '@ng-select/ng-select'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.vendure = global.vendure || {}, global.vendure['admin-ui'] = global.vendure['admin-ui'] || {}, global.vendure['admin-ui'].catalog = {}), global.ng.core, global.ng.router, global.vendure['admin-ui'].core, global.ngxTranslateExtractMarker, global.rxjs.operators, global.ng.forms, global.rxjs, global.normalizeString, global.sharedUtils, global.generatedShopTypes, global.ng.common, global.sharedConstants, global.unique, global.pick, global.ng.cdk.dragDrop, global.ngSelect));
5
+ }(this, (function (exports, i0, i1, i2, ngxTranslateExtractMarker, operators, forms, rxjs, normalizeString, sharedUtils, generatedShopTypes, common, sharedConstants, unique, pick, dragDrop, ngSelect) { 'use strict';
6
6
 
7
7
  function _interopNamespace(e) {
8
8
  if (e && e.__esModule) return e;
@@ -758,7 +758,7 @@
758
758
  CollectionDetailComponent.decorators = [
759
759
  { type: i0.Component, args: [{
760
760
  selector: 'vdr-collection-detail',
761
- template: "<vdr-action-bar>\r\n <vdr-ab-left>\r\n <vdr-entity-info [entity]=\"entity$ | async\"></vdr-entity-info>\r\n <vdr-language-selector\r\n [disabled]=\"isNew$ | async\"\r\n [availableLanguageCodes]=\"availableLanguages$ | async\"\r\n [currentLanguageCode]=\"languageCode$ | async\"\r\n (languageCodeChange)=\"setLanguage($event)\"\r\n ></vdr-language-selector>\r\n </vdr-ab-left>\r\n\r\n <vdr-ab-right>\r\n <vdr-action-bar-items locationId=\"collection-detail\"></vdr-action-bar-items>\r\n <button\r\n class=\"btn btn-primary\"\r\n *ngIf=\"isNew$ | async; else updateButton\"\r\n (click)=\"create()\"\r\n [disabled]=\"detailForm.invalid || detailForm.pristine\"\r\n >\r\n {{ 'common.create' | translate }}\r\n </button>\r\n <ng-template #updateButton>\r\n <button\r\n *vdrIfPermissions=\"updatePermission\"\r\n class=\"btn btn-primary\"\r\n (click)=\"save()\"\r\n [disabled]=\"(detailForm.invalid || detailForm.pristine) && !assetsChanged()\"\r\n >\r\n {{ 'common.update' | translate }}\r\n </button>\r\n </ng-template>\r\n </vdr-ab-right>\r\n</vdr-action-bar>\r\n\r\n<form class=\"form\" [formGroup]=\"detailForm\" *ngIf=\"entity$ | async as category\">\r\n <div class=\"clr-row\">\r\n <div class=\"clr-col\">\r\n <vdr-form-field [label]=\"'catalog.visibility' | translate\" for=\"visibility\">\r\n <clr-toggle-wrapper>\r\n <input\r\n type=\"checkbox\"\r\n clrToggle\r\n formControlName=\"visible\"\r\n id=\"visibility\"\r\n [vdrDisabled]=\"!(updatePermission | hasPermission)\"\r\n />\r\n <label class=\"visible-toggle\">\r\n <ng-container *ngIf=\"detailForm.value.visible; else private\">{{ 'catalog.public' | translate }}</ng-container>\r\n <ng-template #private>{{ 'catalog.private' | translate }}</ng-template>\r\n </label>\r\n </clr-toggle-wrapper>\r\n </vdr-form-field>\r\n <vdr-form-field [label]=\"'common.name' | translate\" for=\"name\">\r\n <input\r\n id=\"name\"\r\n type=\"text\"\r\n formControlName=\"name\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n (input)=\"updateSlug($event.target.value)\"\r\n />\r\n </vdr-form-field>\r\n <vdr-form-field\r\n [label]=\"'catalog.slug' | translate\"\r\n for=\"slug\"\r\n [errors]=\"{ pattern: ('catalog.slug-pattern-error' | translate) }\"\r\n >\r\n <input\r\n id=\"slug\"\r\n type=\"text\"\r\n formControlName=\"slug\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n />\r\n </vdr-form-field>\r\n <vdr-rich-text-editor\r\n formControlName=\"description\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n [label]=\"'common.description' | translate\"\r\n ></vdr-rich-text-editor>\r\n\r\n <section formGroupName=\"customFields\" *ngIf=\"customFields.length\">\r\n <label>{{ 'common.custom-fields' | translate }}</label>\r\n <vdr-tabbed-custom-fields\r\n entityName=\"Collection\"\r\n [customFields]=\"customFields\"\r\n [customFieldsFormGroup]=\"detailForm.get(['customFields'])\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n ></vdr-tabbed-custom-fields>\r\n </section>\r\n <vdr-custom-detail-component-host\r\n locationId=\"collection-detail\"\r\n [entity$]=\"entity$\"\r\n [detailForm]=\"detailForm\"\r\n ></vdr-custom-detail-component-host>\r\n </div>\r\n <div class=\"clr-col-md-auto\">\r\n <vdr-product-assets\r\n [assets]=\"category.assets\"\r\n [featuredAsset]=\"category.featuredAsset\"\r\n (change)=\"assetChanges = $event\"\r\n ></vdr-product-assets>\r\n </div>\r\n </div>\r\n <div class=\"clr-row\" formArrayName=\"filters\">\r\n <div class=\"clr-col\">\r\n <label>{{ 'catalog.filters' | translate }}</label>\r\n <ng-container *ngFor=\"let filter of filters; index as i\">\r\n <vdr-configurable-input\r\n (remove)=\"removeFilter($event)\"\r\n [operation]=\"filter\"\r\n [operationDefinition]=\"getFilterDefinition(filter)\"\r\n [formControlName]=\"i\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n ></vdr-configurable-input>\r\n </ng-container>\r\n\r\n <div *vdrIfPermissions=\"updatePermission\">\r\n <vdr-dropdown>\r\n <button class=\"btn btn-outline\" vdrDropdownTrigger>\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'marketing.add-condition' | translate }}\r\n </button>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-left\">\r\n <button\r\n *ngFor=\"let filter of allFilters\"\r\n type=\"button\"\r\n vdrDropdownItem\r\n (click)=\"addFilter(filter)\"\r\n >\r\n {{ filter.description }}\r\n </button>\r\n </vdr-dropdown-menu>\r\n </vdr-dropdown>\r\n </div>\r\n </div>\r\n <div class=\"clr-col\">\r\n <vdr-collection-contents [collectionId]=\"id\" #collectionContents>\r\n <ng-template let-count>\r\n <div class=\"contents-title\">\r\n {{ 'catalog.collection-contents' | translate }} ({{\r\n 'common.results-count' | translate: { count: count }\r\n }})\r\n </div>\r\n </ng-template>\r\n </vdr-collection-contents>\r\n </div>\r\n </div>\r\n</form>\r\n",
761
+ template: "<vdr-action-bar>\r\n <vdr-ab-left>\r\n <vdr-entity-info [entity]=\"entity$ | async\"></vdr-entity-info>\r\n <vdr-language-selector\r\n [disabled]=\"isNew$ | async\"\r\n [availableLanguageCodes]=\"availableLanguages$ | async\"\r\n [currentLanguageCode]=\"languageCode$ | async\"\r\n (languageCodeChange)=\"setLanguage($event)\"\r\n ></vdr-language-selector>\r\n </vdr-ab-left>\r\n\r\n <vdr-ab-right>\r\n <vdr-action-bar-items locationId=\"collection-detail\"></vdr-action-bar-items>\r\n <button\r\n class=\"btn btn-primary\"\r\n *ngIf=\"isNew$ | async; else updateButton\"\r\n (click)=\"create()\"\r\n [disabled]=\"detailForm.invalid || detailForm.pristine\"\r\n >\r\n {{ 'common.create' | translate }}\r\n </button>\r\n <ng-template #updateButton>\r\n <button\r\n *vdrIfPermissions=\"updatePermission\"\r\n class=\"btn btn-primary\"\r\n (click)=\"save()\"\r\n [disabled]=\"(detailForm.invalid || detailForm.pristine) && !assetsChanged()\"\r\n >\r\n {{ 'common.update' | translate }}\r\n </button>\r\n </ng-template>\r\n </vdr-ab-right>\r\n</vdr-action-bar>\r\n\r\n<form class=\"form\" [formGroup]=\"detailForm\" *ngIf=\"entity$ | async as category\">\r\n <div class=\"clr-row\">\r\n <div class=\"clr-col\">\r\n <vdr-form-field [label]=\"'catalog.visibility' | translate\" for=\"visibility\">\r\n <clr-toggle-wrapper>\r\n <input\r\n type=\"checkbox\"\r\n clrToggle\r\n formControlName=\"visible\"\r\n id=\"visibility\"\r\n [vdrDisabled]=\"!(updatePermission | hasPermission)\"\r\n />\r\n <label class=\"visible-toggle\">\r\n <ng-container *ngIf=\"detailForm.value.visible; else private\">{{ 'catalog.public' | translate }}</ng-container>\r\n <ng-template #private>{{ 'catalog.private' | translate }}</ng-template>\r\n </label>\r\n </clr-toggle-wrapper>\r\n </vdr-form-field>\r\n <vdr-form-field [label]=\"'common.name' | translate\" for=\"name\">\r\n <input\r\n id=\"name\"\r\n type=\"text\"\r\n formControlName=\"name\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n (input)=\"updateSlug($event.target.value)\"\r\n />\r\n </vdr-form-field>\r\n <vdr-form-field\r\n [label]=\"'catalog.slug' | translate\"\r\n for=\"slug\"\r\n [errors]=\"{ pattern: ('catalog.slug-pattern-error' | translate) }\"\r\n >\r\n <input\r\n id=\"slug\"\r\n type=\"text\"\r\n formControlName=\"slug\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n />\r\n </vdr-form-field>\r\n <vdr-rich-text-editor\r\n formControlName=\"description\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n [label]=\"'common.description' | translate\"\r\n ></vdr-rich-text-editor>\r\n\r\n <section formGroupName=\"customFields\" *ngIf=\"customFields.length\">\r\n <label>{{ 'common.custom-fields' | translate }}</label>\r\n <vdr-tabbed-custom-fields\r\n entityName=\"Collection\"\r\n [customFields]=\"customFields\"\r\n [customFieldsFormGroup]=\"detailForm.get(['customFields'])\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n ></vdr-tabbed-custom-fields>\r\n </section>\r\n <vdr-custom-detail-component-host\r\n locationId=\"collection-detail\"\r\n [entity$]=\"entity$\"\r\n [detailForm]=\"detailForm\"\r\n ></vdr-custom-detail-component-host>\r\n </div>\r\n <div class=\"clr-col-md-auto\">\r\n <vdr-assets\r\n [assets]=\"category.assets\"\r\n [featuredAsset]=\"category.featuredAsset\"\r\n [updatePermissions]=\"updatePermission\"\r\n (change)=\"assetChanges = $event\"\r\n ></vdr-assets>\r\n </div>\r\n </div>\r\n <div class=\"clr-row\" formArrayName=\"filters\">\r\n <div class=\"clr-col\">\r\n <label>{{ 'catalog.filters' | translate }}</label>\r\n <ng-container *ngFor=\"let filter of filters; index as i\">\r\n <vdr-configurable-input\r\n (remove)=\"removeFilter($event)\"\r\n [operation]=\"filter\"\r\n [operationDefinition]=\"getFilterDefinition(filter)\"\r\n [formControlName]=\"i\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n ></vdr-configurable-input>\r\n </ng-container>\r\n\r\n <div *vdrIfPermissions=\"updatePermission\">\r\n <vdr-dropdown>\r\n <button class=\"btn btn-outline\" vdrDropdownTrigger>\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'marketing.add-condition' | translate }}\r\n </button>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-left\">\r\n <button\r\n *ngFor=\"let filter of allFilters\"\r\n type=\"button\"\r\n vdrDropdownItem\r\n (click)=\"addFilter(filter)\"\r\n >\r\n {{ filter.description }}\r\n </button>\r\n </vdr-dropdown-menu>\r\n </vdr-dropdown>\r\n </div>\r\n </div>\r\n <div class=\"clr-col\">\r\n <vdr-collection-contents [collectionId]=\"id\" #collectionContents>\r\n <ng-template let-count>\r\n <div class=\"contents-title\">\r\n {{ 'catalog.collection-contents' | translate }} ({{\r\n 'common.results-count' | translate: { count: count }\r\n }})\r\n </div>\r\n </ng-template>\r\n </vdr-collection-contents>\r\n </div>\r\n </div>\r\n</form>\r\n",
762
762
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
763
763
  styles: [".visible-toggle{margin-top:-3px!important}\n"]
764
764
  },] }
@@ -915,8 +915,8 @@
915
915
  name: '',
916
916
  visible: true,
917
917
  customFields: _this.formBuilder.group(_this.customFields.reduce(function (hash, field) {
918
- var _b;
919
- return (Object.assign(Object.assign({}, hash), (_b = {}, _b[field.name] = '', _b)));
918
+ var _f;
919
+ return (Object.assign(Object.assign({}, hash), (_f = {}, _f[field.name] = '', _f)));
920
920
  }, {})),
921
921
  }),
922
922
  values: _this.formBuilder.array([]),
@@ -952,14 +952,36 @@
952
952
  return this.detailForm.get('values');
953
953
  };
954
954
  FacetDetailComponent.prototype.addFacetValue = function () {
955
+ var e_1, _f;
955
956
  var valuesFormArray = this.detailForm.get('values');
956
957
  if (valuesFormArray) {
957
- valuesFormArray.insert(valuesFormArray.length, this.formBuilder.group({
958
+ var valueGroup = this.formBuilder.group({
958
959
  id: '',
959
960
  name: ['', forms.Validators.required],
960
961
  code: '',
961
- }));
962
- this.values.push({ name: '', code: '' });
962
+ });
963
+ var newValue = { name: '', code: '' };
964
+ if (this.customValueFields.length) {
965
+ var customValueFieldsGroup = new forms.FormGroup({});
966
+ newValue.customFields = {};
967
+ try {
968
+ for (var _g = __values(this.customValueFields), _h = _g.next(); !_h.done; _h = _g.next()) {
969
+ var fieldDef = _h.value;
970
+ var key = fieldDef.name;
971
+ customValueFieldsGroup.addControl(key, new forms.FormControl());
972
+ }
973
+ }
974
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
975
+ finally {
976
+ try {
977
+ if (_h && !_h.done && (_f = _g.return)) _f.call(_g);
978
+ }
979
+ finally { if (e_1) throw e_1.error; }
980
+ }
981
+ valueGroup.addControl('customFields', customValueFieldsGroup);
982
+ }
983
+ valuesFormArray.insert(valuesFormArray.length, valueGroup);
984
+ this.values.push(newValue);
963
985
  }
964
986
  };
965
987
  FacetDetailComponent.prototype.create = function () {
@@ -969,8 +991,8 @@
969
991
  return;
970
992
  }
971
993
  rxjs.combineLatest(this.entity$, this.languageCode$)
972
- .pipe(operators.take(1), operators.mergeMap(function (_b) {
973
- var _c = __read(_b, 2), facet = _c[0], languageCode = _c[1];
994
+ .pipe(operators.take(1), operators.mergeMap(function (_f) {
995
+ var _g = __read(_f, 2), facet = _g[0], languageCode = _g[1];
974
996
  var newFacet = _this.getUpdatedFacet(facet, facetForm, languageCode);
975
997
  return _this.dataService.facet.createFacet(newFacet);
976
998
  }), operators.switchMap(function (data) { return _this.dataService.facet.getAllFacets().single$.pipe(operators.mapTo(data)); }))
@@ -988,8 +1010,8 @@
988
1010
  FacetDetailComponent.prototype.save = function () {
989
1011
  var _this = this;
990
1012
  rxjs.combineLatest(this.entity$, this.languageCode$)
991
- .pipe(operators.take(1), operators.mergeMap(function (_b) {
992
- var _c = __read(_b, 2), facet = _c[0], languageCode = _c[1];
1013
+ .pipe(operators.take(1), operators.mergeMap(function (_f) {
1014
+ var _g = __read(_f, 2), facet = _g[0], languageCode = _g[1];
993
1015
  var facetGroup = _this.detailForm.get('facet');
994
1016
  var updateOperations = [];
995
1017
  if (facetGroup && facetGroup.dirty) {
@@ -1000,16 +1022,10 @@
1000
1022
  }
1001
1023
  var valuesArray = _this.detailForm.get('values');
1002
1024
  if (valuesArray && valuesArray.dirty) {
1003
- var newValues = valuesArray.controls
1004
- .filter(function (c) { return !c.value.id; })
1005
- .map(function (c) { return ({
1006
- facetId: facet.id,
1007
- code: c.value.code,
1008
- translations: [{ name: c.value.name, languageCode: languageCode }],
1009
- }); });
1010
- if (newValues.length) {
1025
+ var createdValues = _this.getCreatedFacetValues(facet, valuesArray, languageCode);
1026
+ if (createdValues.length) {
1011
1027
  updateOperations.push(_this.dataService.facet
1012
- .createFacetValues(newValues)
1028
+ .createFacetValues(createdValues)
1013
1029
  .pipe(operators.switchMap(function () { return _this.dataService.facet.getFacet(_this.id).single$; })));
1014
1030
  }
1015
1031
  var updatedValues = _this.getUpdatedFacetValues(facet, valuesArray, languageCode);
@@ -1093,7 +1109,8 @@
1093
1109
  var currentValuesFormArray = this.detailForm.get('values');
1094
1110
  this.values = __spreadArray([], __read(facet.values));
1095
1111
  facet.values.forEach(function (value, i) {
1096
- var e_1, _b;
1112
+ var e_2, _f;
1113
+ var _a, _b, _c, _d, _e;
1097
1114
  var valueTranslation = i2.findTranslation(value, languageCode);
1098
1115
  var group = {
1099
1116
  id: value.id,
@@ -1102,7 +1119,9 @@
1102
1119
  };
1103
1120
  var valueControl = currentValuesFormArray.at(i);
1104
1121
  if (valueControl) {
1105
- valueControl.setValue(group);
1122
+ (_a = valueControl.get('id')) === null || _a === void 0 ? void 0 : _a.setValue(group.id);
1123
+ (_b = valueControl.get('code')) === null || _b === void 0 ? void 0 : _b.setValue(group.code);
1124
+ (_c = valueControl.get('name')) === null || _c === void 0 ? void 0 : _c.setValue(group.name);
1106
1125
  }
1107
1126
  else {
1108
1127
  currentValuesFormArray.insert(i, _this.formBuilder.group(group));
@@ -1115,11 +1134,11 @@
1115
1134
  }
1116
1135
  if (customValueFieldsGroup) {
1117
1136
  try {
1118
- for (var _c = __values(_this.customValueFields), _d = _c.next(); !_d.done; _d = _c.next()) {
1119
- var fieldDef = _d.value;
1137
+ for (var _g = __values(_this.customValueFields), _h = _g.next(); !_h.done; _h = _g.next()) {
1138
+ var fieldDef = _h.value;
1120
1139
  var key = fieldDef.name;
1121
1140
  var fieldValue = fieldDef.type === 'localeString'
1122
- ? valueTranslation.customFields[key]
1141
+ ? (_e = (_d = valueTranslation) === null || _d === void 0 ? void 0 : _d.customFields) === null || _e === void 0 ? void 0 : _e[key]
1123
1142
  : value.customFields[key];
1124
1143
  var control = customValueFieldsGroup.get(key);
1125
1144
  if (control) {
@@ -1130,12 +1149,12 @@
1130
1149
  }
1131
1150
  }
1132
1151
  }
1133
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1152
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
1134
1153
  finally {
1135
1154
  try {
1136
- if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
1155
+ if (_h && !_h.done && (_f = _g.return)) _f.call(_g);
1137
1156
  }
1138
- finally { if (e_1) throw e_1.error; }
1157
+ finally { if (e_2) throw e_2.error; }
1139
1158
  }
1140
1159
  }
1141
1160
  }
@@ -1160,8 +1179,29 @@
1160
1179
  return input;
1161
1180
  };
1162
1181
  /**
1163
- * Given an array of facet values and the values from the detailForm, this method creates an new array
1164
- * which can be persisted to the API.
1182
+ * Given an array of facet values and the values from the detailForm, this method creates a new array
1183
+ * which can be persisted to the API via a createFacetValues mutation.
1184
+ */
1185
+ FacetDetailComponent.prototype.getCreatedFacetValues = function (facet, valuesFormArray, languageCode) {
1186
+ var _this = this;
1187
+ return valuesFormArray.controls
1188
+ .filter(function (c) { return !c.value.id; })
1189
+ .map(function (c) { return c.value; })
1190
+ .map(function (value) { return i2.createUpdatedTranslatable({
1191
+ translatable: Object.assign(Object.assign({}, value), { translations: [] }),
1192
+ updatedFields: value,
1193
+ customFieldConfig: _this.customValueFields,
1194
+ languageCode: languageCode,
1195
+ defaultTranslation: {
1196
+ languageCode: languageCode,
1197
+ name: '',
1198
+ },
1199
+ }); })
1200
+ .map(function (input) { return (Object.assign({ facetId: facet.id }, input)); });
1201
+ };
1202
+ /**
1203
+ * Given an array of facet values and the values from the detailForm, this method creates a new array
1204
+ * which can be persisted to the API via an updateFacetValues mutation.
1165
1205
  */
1166
1206
  FacetDetailComponent.prototype.getUpdatedFacetValues = function (facet, valuesFormArray, languageCode) {
1167
1207
  var _this = this;
@@ -1784,6 +1824,7 @@
1784
1824
  // Used to store all ProductVariants which have been loaded.
1785
1825
  // It is needed when saving changes to variants.
1786
1826
  _this.productVariantMap = new Map();
1827
+ _this.updatePermissions = [i2.Permission.UpdateCatalog, i2.Permission.UpdateProduct];
1787
1828
  _this.customFields = _this.getCustomFieldConfig('Product');
1788
1829
  _this.customVariantFields = _this.getCustomFieldConfig('ProductVariant');
1789
1830
  _this.customOptionGroupFields = _this.getCustomFieldConfig('ProductOptionGroup');
@@ -2307,7 +2348,7 @@
2307
2348
  ProductDetailComponent.decorators = [
2308
2349
  { type: i0.Component, args: [{
2309
2350
  selector: 'vdr-product-detail',
2310
- template: "<vdr-action-bar>\r\n <vdr-ab-left>\r\n <div class=\"flex clr-flex-row\">\r\n <vdr-entity-info [entity]=\"entity$ | async\"></vdr-entity-info>\r\n <clr-toggle-wrapper *vdrIfPermissions=\"['UpdateCatalog', 'UpdateProduct']\">\r\n <input\r\n type=\"checkbox\"\r\n clrToggle\r\n name=\"enabled\"\r\n [formControl]=\"detailForm.get(['product', 'enabled'])\"\r\n />\r\n <label>{{ 'common.enabled' | translate }}</label>\r\n </clr-toggle-wrapper>\r\n </div>\r\n <vdr-language-selector\r\n [disabled]=\"isNew$ | async\"\r\n [availableLanguageCodes]=\"availableLanguages$ | async\"\r\n [currentLanguageCode]=\"languageCode$ | async\"\r\n (languageCodeChange)=\"setLanguage($event)\"\r\n ></vdr-language-selector>\r\n </vdr-ab-left>\r\n\r\n <vdr-ab-right>\r\n <vdr-action-bar-items locationId=\"product-detail\"></vdr-action-bar-items>\r\n <button\r\n class=\"btn btn-primary\"\r\n *ngIf=\"isNew$ | async; else updateButton\"\r\n (click)=\"create()\"\r\n [disabled]=\"detailForm.invalid || detailForm.pristine || !variantsToCreateAreValid()\"\r\n >\r\n {{ 'common.create' | translate }}\r\n </button>\r\n <ng-template #updateButton>\r\n <button\r\n *vdrIfPermissions=\"['UpdateCatalog', 'UpdateProduct']\"\r\n class=\"btn btn-primary\"\r\n (click)=\"save()\"\r\n [disabled]=\"\r\n (detailForm.invalid || detailForm.pristine) && !assetsChanged() && !variantAssetsChanged()\r\n \"\r\n >\r\n {{ 'common.update' | translate }}\r\n </button>\r\n </ng-template>\r\n </vdr-ab-right>\r\n</vdr-action-bar>\r\n\r\n<form class=\"form\" [formGroup]=\"detailForm\" *ngIf=\"product$ | async as product\">\r\n <button type=\"submit\" hidden x-data=\"prevents enter key from triggering other buttons\"></button>\r\n <clr-tabs>\r\n <clr-tab>\r\n <button clrTabLink (click)=\"navigateToTab('details')\">\r\n {{ 'catalog.product-details' | translate }}\r\n </button>\r\n <clr-tab-content *clrIfActive=\"(activeTab$ | async) === 'details'\">\r\n <div class=\"clr-row\">\r\n <div class=\"clr-col\">\r\n <section class=\"form-block\" formGroupName=\"product\">\r\n <ng-container *ngIf=\"!(isNew$ | async)\">\r\n <ng-container *vdrIfMultichannel>\r\n <vdr-form-item\r\n [label]=\"'common.channels' | translate\"\r\n *vdrIfDefaultChannelActive\r\n >\r\n <div class=\"flex channel-assignment\">\r\n <ng-container *ngFor=\"let channel of productChannels$ | async\">\r\n <vdr-chip\r\n *ngIf=\"!isDefaultChannel(channel.code)\"\r\n icon=\"times-circle\"\r\n (iconClick)=\"removeFromChannel(channel.id)\"\r\n >\r\n <vdr-channel-badge\r\n [channelCode]=\"channel.code\"\r\n ></vdr-channel-badge>\r\n {{ channel.code | channelCodeToLabel }}\r\n </vdr-chip>\r\n </ng-container>\r\n <button class=\"btn btn-sm\" (click)=\"assignToChannel()\">\r\n <clr-icon shape=\"layers\"></clr-icon>\r\n {{ 'catalog.assign-to-channel' | translate }}\r\n </button>\r\n </div>\r\n </vdr-form-item>\r\n </ng-container>\r\n </ng-container>\r\n <vdr-form-field [label]=\"'catalog.product-name' | translate\" for=\"name\">\r\n <input\r\n id=\"name\"\r\n type=\"text\"\r\n formControlName=\"name\"\r\n [readonly]=\"!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)\"\r\n (input)=\"updateSlug($event.target.value)\"\r\n />\r\n </vdr-form-field>\r\n <div\r\n class=\"auto-rename-wrapper\"\r\n [class.visible]=\"\r\n (isNew$ | async) === false && detailForm.get(['product', 'name'])?.dirty\r\n \"\r\n >\r\n <clr-checkbox-wrapper>\r\n <input\r\n clrCheckbox\r\n type=\"checkbox\"\r\n id=\"auto-update\"\r\n formControlName=\"autoUpdateVariantNames\"\r\n />\r\n <label>{{\r\n 'catalog.auto-update-product-variant-name' | translate\r\n }}</label>\r\n </clr-checkbox-wrapper>\r\n </div>\r\n <vdr-form-field\r\n [label]=\"'catalog.slug' | translate\"\r\n for=\"slug\"\r\n [errors]=\"{ pattern: 'catalog.slug-pattern-error' | translate }\"\r\n >\r\n <input\r\n id=\"slug\"\r\n type=\"text\"\r\n formControlName=\"slug\"\r\n [readonly]=\"!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)\"\r\n />\r\n </vdr-form-field>\r\n <vdr-rich-text-editor\r\n formControlName=\"description\"\r\n [readonly]=\"!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)\"\r\n [label]=\"'common.description' | translate\"\r\n ></vdr-rich-text-editor>\r\n\r\n <section formGroupName=\"customFields\" *ngIf=\"customFields.length\">\r\n <label>{{ 'common.custom-fields' | translate }}</label>\r\n <vdr-tabbed-custom-fields\r\n entityName=\"Product\"\r\n [customFields]=\"customFields\"\r\n [customFieldsFormGroup]=\"detailForm.get(['product', 'customFields'])\"\r\n [readonly]=\"!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)\"\r\n ></vdr-tabbed-custom-fields>\r\n </section>\r\n <vdr-custom-detail-component-host\r\n locationId=\"product-detail\"\r\n [entity$]=\"entity$\"\r\n [detailForm]=\"detailForm\"\r\n ></vdr-custom-detail-component-host>\r\n </section>\r\n </div>\r\n <div class=\"clr-col-md-auto\">\r\n <vdr-product-assets\r\n [assets]=\"assetChanges.assets || product.assets\"\r\n [featuredAsset]=\"assetChanges.featuredAsset || product.featuredAsset\"\r\n (change)=\"assetChanges = $event\"\r\n ></vdr-product-assets>\r\n <div class=\"facets\">\r\n <vdr-facet-value-chip\r\n *ngFor=\"let facetValue of facetValues$ | async\"\r\n [facetValue]=\"facetValue\"\r\n [removable]=\"['UpdateCatalog', 'UpdateProduct'] | hasPermission\"\r\n (remove)=\"removeProductFacetValue(facetValue.id)\"\r\n ></vdr-facet-value-chip>\r\n <button\r\n class=\"btn btn-sm btn-secondary\"\r\n *vdrIfPermissions=\"['UpdateCatalog', 'UpdateProduct']\"\r\n (click)=\"selectProductFacetValue()\"\r\n >\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.add-facets' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"isNew$ | async\">\r\n <h4>{{ 'catalog.product-variants' | translate }}</h4>\r\n <vdr-generate-product-variants\r\n (variantsChange)=\"createVariantsConfig = $event\"\r\n ></vdr-generate-product-variants>\r\n </div>\r\n </clr-tab-content>\r\n </clr-tab>\r\n <clr-tab *ngIf=\"!(isNew$ | async)\">\r\n <button clrTabLink (click)=\"navigateToTab('variants')\">\r\n {{ 'catalog.product-variants' | translate }}\r\n </button>\r\n <clr-tab-content *clrIfActive=\"(activeTab$ | async) === 'variants'\">\r\n <section class=\"form-block\">\r\n <div class=\"view-mode\">\r\n <div class=\"btn-group\">\r\n <button\r\n class=\"btn btn-secondary-outline\"\r\n (click)=\"variantDisplayMode = 'card'\"\r\n [class.btn-primary]=\"variantDisplayMode === 'card'\"\r\n >\r\n <clr-icon shape=\"list\"></clr-icon>\r\n {{ 'catalog.display-variant-cards' | translate }}\r\n </button>\r\n <button\r\n class=\"btn\"\r\n (click)=\"variantDisplayMode = 'table'\"\r\n [class.btn-primary]=\"variantDisplayMode === 'table'\"\r\n >\r\n <clr-icon shape=\"table\"></clr-icon>\r\n {{ 'catalog.display-variant-table' | translate }}\r\n </button>\r\n </div>\r\n <div class=\"variant-filter\">\r\n <input\r\n [formControl]=\"filterInput\"\r\n [placeholder]=\"'catalog.filter-by-name-or-sku' | translate\"\r\n />\r\n <button class=\"icon-button\" (click)=\"filterInput.setValue('')\">\r\n <clr-icon shape=\"times\"></clr-icon>\r\n </button>\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <a\r\n *vdrIfPermissions=\"['UpdateCatalog', 'UpdateProduct']\"\r\n [routerLink]=\"['./', 'manage-variants']\"\r\n class=\"btn btn-secondary edit-variants-btn\"\r\n >\r\n <clr-icon shape=\"add-text\"></clr-icon>\r\n {{ 'catalog.manage-variants' | translate }}\r\n </a>\r\n </div>\r\n\r\n <div class=\"pagination-row mt4\" *ngIf=\"10 < (paginationConfig$ | async)?.totalItems\">\r\n <vdr-items-per-page-controls\r\n [itemsPerPage]=\"itemsPerPage$ | async\"\r\n (itemsPerPageChange)=\"setItemsPerPage($event)\"\r\n ></vdr-items-per-page-controls>\r\n\r\n <vdr-pagination-controls\r\n [id]=\"(paginationConfig$ | async)?.id\"\r\n [currentPage]=\"currentPage$ | async\"\r\n [itemsPerPage]=\"itemsPerPage$ | async\"\r\n (pageChange)=\"setPage($event)\"\r\n ></vdr-pagination-controls>\r\n </div>\r\n\r\n <vdr-product-variants-table\r\n *ngIf=\"variantDisplayMode === 'table'\"\r\n [variants]=\"variants$ | async\"\r\n [paginationConfig]=\"paginationConfig$ | async\"\r\n [optionGroups]=\"product.optionGroups\"\r\n [channelPriceIncludesTax]=\"channelPriceIncludesTax$ | async\"\r\n [productVariantsFormArray]=\"detailForm.get('variants')\"\r\n [pendingAssetChanges]=\"variantAssetChanges\"\r\n ></vdr-product-variants-table>\r\n <vdr-product-variants-list\r\n *ngIf=\"variantDisplayMode === 'card'\"\r\n [variants]=\"variants$ | async\"\r\n [paginationConfig]=\"paginationConfig$ | async\"\r\n [channelPriceIncludesTax]=\"channelPriceIncludesTax$ | async\"\r\n [facets]=\"facets$ | async\"\r\n [optionGroups]=\"product.optionGroups\"\r\n [productVariantsFormArray]=\"detailForm.get('variants')\"\r\n [taxCategories]=\"taxCategories$ | async\"\r\n [customFields]=\"customVariantFields\"\r\n [customOptionFields]=\"customOptionFields\"\r\n [activeLanguage]=\"languageCode$ | async\"\r\n [pendingAssetChanges]=\"variantAssetChanges\"\r\n (assignToChannel)=\"assignVariantToChannel($event)\"\r\n (removeFromChannel)=\"removeVariantFromChannel($event)\"\r\n (assetChange)=\"variantAssetChange($event)\"\r\n (updateProductOption)=\"updateProductOption($event)\"\r\n (selectionChange)=\"selectedVariantIds = $event\"\r\n (selectFacetValueClick)=\"selectVariantFacetValue($event)\"\r\n ></vdr-product-variants-list>\r\n </section>\r\n <div class=\"pagination-row mt4\" *ngIf=\"10 < (paginationConfig$ | async)?.totalItems\">\r\n <vdr-items-per-page-controls\r\n [itemsPerPage]=\"itemsPerPage$ | async\"\r\n (itemsPerPageChange)=\"setItemsPerPage($event)\"\r\n ></vdr-items-per-page-controls>\r\n\r\n <vdr-pagination-controls\r\n [id]=\"(paginationConfig$ | async)?.id\"\r\n [currentPage]=\"currentPage$ | async\"\r\n [itemsPerPage]=\"itemsPerPage$ | async\"\r\n (pageChange)=\"setPage($event)\"\r\n ></vdr-pagination-controls>\r\n </div>\r\n </clr-tab-content>\r\n </clr-tab>\r\n </clr-tabs>\r\n</form>\r\n",
2351
+ template: "<vdr-action-bar>\r\n <vdr-ab-left>\r\n <div class=\"flex clr-flex-row\">\r\n <vdr-entity-info [entity]=\"entity$ | async\"></vdr-entity-info>\r\n <clr-toggle-wrapper *vdrIfPermissions=\"['UpdateCatalog', 'UpdateProduct']\">\r\n <input\r\n type=\"checkbox\"\r\n clrToggle\r\n name=\"enabled\"\r\n [formControl]=\"detailForm.get(['product', 'enabled'])\"\r\n />\r\n <label>{{ 'common.enabled' | translate }}</label>\r\n </clr-toggle-wrapper>\r\n </div>\r\n <vdr-language-selector\r\n [disabled]=\"isNew$ | async\"\r\n [availableLanguageCodes]=\"availableLanguages$ | async\"\r\n [currentLanguageCode]=\"languageCode$ | async\"\r\n (languageCodeChange)=\"setLanguage($event)\"\r\n ></vdr-language-selector>\r\n </vdr-ab-left>\r\n\r\n <vdr-ab-right>\r\n <vdr-action-bar-items locationId=\"product-detail\"></vdr-action-bar-items>\r\n <button\r\n class=\"btn btn-primary\"\r\n *ngIf=\"isNew$ | async; else updateButton\"\r\n (click)=\"create()\"\r\n [disabled]=\"detailForm.invalid || detailForm.pristine || !variantsToCreateAreValid()\"\r\n >\r\n {{ 'common.create' | translate }}\r\n </button>\r\n <ng-template #updateButton>\r\n <button\r\n *vdrIfPermissions=\"['UpdateCatalog', 'UpdateProduct']\"\r\n class=\"btn btn-primary\"\r\n (click)=\"save()\"\r\n [disabled]=\"\r\n (detailForm.invalid || detailForm.pristine) && !assetsChanged() && !variantAssetsChanged()\r\n \"\r\n >\r\n {{ 'common.update' | translate }}\r\n </button>\r\n </ng-template>\r\n </vdr-ab-right>\r\n</vdr-action-bar>\r\n\r\n<form class=\"form\" [formGroup]=\"detailForm\" *ngIf=\"product$ | async as product\">\r\n <button type=\"submit\" hidden x-data=\"prevents enter key from triggering other buttons\"></button>\r\n <clr-tabs>\r\n <clr-tab>\r\n <button clrTabLink (click)=\"navigateToTab('details')\">\r\n {{ 'catalog.product-details' | translate }}\r\n </button>\r\n <clr-tab-content *clrIfActive=\"(activeTab$ | async) === 'details'\">\r\n <div class=\"clr-row\">\r\n <div class=\"clr-col\">\r\n <section class=\"form-block\" formGroupName=\"product\">\r\n <ng-container *ngIf=\"!(isNew$ | async)\">\r\n <ng-container *vdrIfMultichannel>\r\n <vdr-form-item\r\n [label]=\"'common.channels' | translate\"\r\n *vdrIfDefaultChannelActive\r\n >\r\n <div class=\"flex channel-assignment\">\r\n <ng-container *ngFor=\"let channel of productChannels$ | async\">\r\n <vdr-chip\r\n *ngIf=\"!isDefaultChannel(channel.code)\"\r\n icon=\"times-circle\"\r\n (iconClick)=\"removeFromChannel(channel.id)\"\r\n >\r\n <vdr-channel-badge\r\n [channelCode]=\"channel.code\"\r\n ></vdr-channel-badge>\r\n {{ channel.code | channelCodeToLabel }}\r\n </vdr-chip>\r\n </ng-container>\r\n <button class=\"btn btn-sm\" (click)=\"assignToChannel()\">\r\n <clr-icon shape=\"layers\"></clr-icon>\r\n {{ 'catalog.assign-to-channel' | translate }}\r\n </button>\r\n </div>\r\n </vdr-form-item>\r\n </ng-container>\r\n </ng-container>\r\n <vdr-form-field [label]=\"'catalog.product-name' | translate\" for=\"name\">\r\n <input\r\n id=\"name\"\r\n type=\"text\"\r\n formControlName=\"name\"\r\n [readonly]=\"!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)\"\r\n (input)=\"updateSlug($event.target.value)\"\r\n />\r\n </vdr-form-field>\r\n <div\r\n class=\"auto-rename-wrapper\"\r\n [class.visible]=\"\r\n (isNew$ | async) === false && detailForm.get(['product', 'name'])?.dirty\r\n \"\r\n >\r\n <clr-checkbox-wrapper>\r\n <input\r\n clrCheckbox\r\n type=\"checkbox\"\r\n id=\"auto-update\"\r\n formControlName=\"autoUpdateVariantNames\"\r\n />\r\n <label>{{\r\n 'catalog.auto-update-product-variant-name' | translate\r\n }}</label>\r\n </clr-checkbox-wrapper>\r\n </div>\r\n <vdr-form-field\r\n [label]=\"'catalog.slug' | translate\"\r\n for=\"slug\"\r\n [errors]=\"{ pattern: 'catalog.slug-pattern-error' | translate }\"\r\n >\r\n <input\r\n id=\"slug\"\r\n type=\"text\"\r\n formControlName=\"slug\"\r\n [readonly]=\"!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)\"\r\n />\r\n </vdr-form-field>\r\n <vdr-rich-text-editor\r\n formControlName=\"description\"\r\n [readonly]=\"!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)\"\r\n [label]=\"'common.description' | translate\"\r\n ></vdr-rich-text-editor>\r\n\r\n <section formGroupName=\"customFields\" *ngIf=\"customFields.length\">\r\n <label>{{ 'common.custom-fields' | translate }}</label>\r\n <vdr-tabbed-custom-fields\r\n entityName=\"Product\"\r\n [customFields]=\"customFields\"\r\n [customFieldsFormGroup]=\"detailForm.get(['product', 'customFields'])\"\r\n [readonly]=\"!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)\"\r\n ></vdr-tabbed-custom-fields>\r\n </section>\r\n <vdr-custom-detail-component-host\r\n locationId=\"product-detail\"\r\n [entity$]=\"entity$\"\r\n [detailForm]=\"detailForm\"\r\n ></vdr-custom-detail-component-host>\r\n </section>\r\n </div>\r\n <div class=\"clr-col-md-auto\">\r\n <vdr-assets\r\n [assets]=\"assetChanges.assets || product.assets\"\r\n [featuredAsset]=\"assetChanges.featuredAsset || product.featuredAsset\"\r\n [updatePermissions]=\"updatePermissions\"\r\n (change)=\"assetChanges = $event\"\r\n ></vdr-assets>\r\n <div class=\"facets\">\r\n <vdr-facet-value-chip\r\n *ngFor=\"let facetValue of facetValues$ | async\"\r\n [facetValue]=\"facetValue\"\r\n [removable]=\"['UpdateCatalog', 'UpdateProduct'] | hasPermission\"\r\n (remove)=\"removeProductFacetValue(facetValue.id)\"\r\n ></vdr-facet-value-chip>\r\n <button\r\n class=\"btn btn-sm btn-secondary\"\r\n *vdrIfPermissions=\"['UpdateCatalog', 'UpdateProduct']\"\r\n (click)=\"selectProductFacetValue()\"\r\n >\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.add-facets' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"isNew$ | async\">\r\n <h4>{{ 'catalog.product-variants' | translate }}</h4>\r\n <vdr-generate-product-variants\r\n (variantsChange)=\"createVariantsConfig = $event\"\r\n ></vdr-generate-product-variants>\r\n </div>\r\n </clr-tab-content>\r\n </clr-tab>\r\n <clr-tab *ngIf=\"!(isNew$ | async)\">\r\n <button clrTabLink (click)=\"navigateToTab('variants')\">\r\n {{ 'catalog.product-variants' | translate }}\r\n </button>\r\n <clr-tab-content *clrIfActive=\"(activeTab$ | async) === 'variants'\">\r\n <section class=\"form-block\">\r\n <div class=\"view-mode\">\r\n <div class=\"btn-group\">\r\n <button\r\n class=\"btn btn-secondary-outline\"\r\n (click)=\"variantDisplayMode = 'card'\"\r\n [class.btn-primary]=\"variantDisplayMode === 'card'\"\r\n >\r\n <clr-icon shape=\"list\"></clr-icon>\r\n {{ 'catalog.display-variant-cards' | translate }}\r\n </button>\r\n <button\r\n class=\"btn\"\r\n (click)=\"variantDisplayMode = 'table'\"\r\n [class.btn-primary]=\"variantDisplayMode === 'table'\"\r\n >\r\n <clr-icon shape=\"table\"></clr-icon>\r\n {{ 'catalog.display-variant-table' | translate }}\r\n </button>\r\n </div>\r\n <div class=\"variant-filter\">\r\n <input\r\n [formControl]=\"filterInput\"\r\n [placeholder]=\"'catalog.filter-by-name-or-sku' | translate\"\r\n />\r\n <button class=\"icon-button\" (click)=\"filterInput.setValue('')\">\r\n <clr-icon shape=\"times\"></clr-icon>\r\n </button>\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <a\r\n *vdrIfPermissions=\"['UpdateCatalog', 'UpdateProduct']\"\r\n [routerLink]=\"['./', 'manage-variants']\"\r\n class=\"btn btn-secondary edit-variants-btn\"\r\n >\r\n <clr-icon shape=\"add-text\"></clr-icon>\r\n {{ 'catalog.manage-variants' | translate }}\r\n </a>\r\n </div>\r\n\r\n <div class=\"pagination-row mt4\" *ngIf=\"10 < (paginationConfig$ | async)?.totalItems\">\r\n <vdr-items-per-page-controls\r\n [itemsPerPage]=\"itemsPerPage$ | async\"\r\n (itemsPerPageChange)=\"setItemsPerPage($event)\"\r\n ></vdr-items-per-page-controls>\r\n\r\n <vdr-pagination-controls\r\n [id]=\"(paginationConfig$ | async)?.id\"\r\n [currentPage]=\"currentPage$ | async\"\r\n [itemsPerPage]=\"itemsPerPage$ | async\"\r\n (pageChange)=\"setPage($event)\"\r\n ></vdr-pagination-controls>\r\n </div>\r\n\r\n <vdr-product-variants-table\r\n *ngIf=\"variantDisplayMode === 'table'\"\r\n [variants]=\"variants$ | async\"\r\n [paginationConfig]=\"paginationConfig$ | async\"\r\n [optionGroups]=\"product.optionGroups\"\r\n [channelPriceIncludesTax]=\"channelPriceIncludesTax$ | async\"\r\n [productVariantsFormArray]=\"detailForm.get('variants')\"\r\n [pendingAssetChanges]=\"variantAssetChanges\"\r\n ></vdr-product-variants-table>\r\n <vdr-product-variants-list\r\n *ngIf=\"variantDisplayMode === 'card'\"\r\n [variants]=\"variants$ | async\"\r\n [paginationConfig]=\"paginationConfig$ | async\"\r\n [channelPriceIncludesTax]=\"channelPriceIncludesTax$ | async\"\r\n [facets]=\"facets$ | async\"\r\n [optionGroups]=\"product.optionGroups\"\r\n [productVariantsFormArray]=\"detailForm.get('variants')\"\r\n [taxCategories]=\"taxCategories$ | async\"\r\n [customFields]=\"customVariantFields\"\r\n [customOptionFields]=\"customOptionFields\"\r\n [activeLanguage]=\"languageCode$ | async\"\r\n [pendingAssetChanges]=\"variantAssetChanges\"\r\n (assignToChannel)=\"assignVariantToChannel($event)\"\r\n (removeFromChannel)=\"removeVariantFromChannel($event)\"\r\n (assetChange)=\"variantAssetChange($event)\"\r\n (updateProductOption)=\"updateProductOption($event)\"\r\n (selectionChange)=\"selectedVariantIds = $event\"\r\n (selectFacetValueClick)=\"selectVariantFacetValue($event)\"\r\n ></vdr-product-variants-list>\r\n </section>\r\n <div class=\"pagination-row mt4\" *ngIf=\"10 < (paginationConfig$ | async)?.totalItems\">\r\n <vdr-items-per-page-controls\r\n [itemsPerPage]=\"itemsPerPage$ | async\"\r\n (itemsPerPageChange)=\"setItemsPerPage($event)\"\r\n ></vdr-items-per-page-controls>\r\n\r\n <vdr-pagination-controls\r\n [id]=\"(paginationConfig$ | async)?.id\"\r\n [currentPage]=\"currentPage$ | async\"\r\n [itemsPerPage]=\"itemsPerPage$ | async\"\r\n (pageChange)=\"setPage($event)\"\r\n ></vdr-pagination-controls>\r\n </div>\r\n </clr-tab-content>\r\n </clr-tab>\r\n </clr-tabs>\r\n</form>\r\n",
2311
2352
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
2312
2353
  styles: [":host ::ng-deep trix-toolbar{top:24px}.facets{margin-top:12px;display:flex;flex-wrap:wrap;align-items:center}@media screen and (min-width: 768px){.facets{max-width:340px}}vdr-action-bar clr-toggle-wrapper{margin-top:12px}.variant-filter{flex:1;display:flex}.variant-filter input{flex:1;max-width:initial;border-radius:3px 0 0 3px!important}.variant-filter .icon-button{border:1px solid var(--color-component-border-300);background-color:var(--color-component-bg-100);border-radius:0 3px 3px 0;border-left:none}.group-name{padding-right:6px}.view-mode{display:flex;justify-content:flex-end;align-items:center}.edit-variants-btn{margin-top:0}.channel-assignment{flex-wrap:wrap}.auto-rename-wrapper{overflow:hidden;max-height:0;padding-left:9.5rem;margin-bottom:0;transition:max-height .2s,margin-bottom .2s}.auto-rename-wrapper.visible{max-height:24px;margin-bottom:12px}.pagination-row{display:flex;align-items:baseline;justify-content:space-between}\n"]
2313
2354
  },] }
@@ -3363,6 +3404,101 @@
3363
3404
  });
3364
3405
  }
3365
3406
 
3407
+ /**
3408
+ * A component which displays the Assets, and allows assets to be removed and
3409
+ * added, and for the featured asset to be set.
3410
+ *
3411
+ * Note: rather complex code for drag drop is due to a limitation of the default CDK implementation
3412
+ * which is addressed by a work-around from here: https://github.com/angular/components/issues/13372#issuecomment-483998378
3413
+ */
3414
+ var AssetsComponent = /** @class */ (function () {
3415
+ function AssetsComponent(modalService, changeDetector) {
3416
+ this.modalService = modalService;
3417
+ this.changeDetector = changeDetector;
3418
+ this.compact = false;
3419
+ this.change = new i0.EventEmitter();
3420
+ this.assets = [];
3421
+ }
3422
+ Object.defineProperty(AssetsComponent.prototype, "assetsSetter", {
3423
+ set: function (val) {
3424
+ // create a new non-readonly array of assets
3425
+ this.assets = (val || []).slice();
3426
+ },
3427
+ enumerable: false,
3428
+ configurable: true
3429
+ });
3430
+ AssetsComponent.prototype.selectAssets = function () {
3431
+ var _this = this;
3432
+ this.modalService
3433
+ .fromComponent(i2.AssetPickerDialogComponent, {
3434
+ size: 'xl',
3435
+ })
3436
+ .subscribe(function (result) {
3437
+ if (result && result.length) {
3438
+ _this.assets = unique.unique(_this.assets.concat(result), 'id');
3439
+ if (!_this.featuredAsset) {
3440
+ _this.featuredAsset = result[0];
3441
+ }
3442
+ _this.emitChangeEvent(_this.assets, _this.featuredAsset);
3443
+ _this.changeDetector.markForCheck();
3444
+ }
3445
+ });
3446
+ };
3447
+ AssetsComponent.prototype.setAsFeatured = function (asset) {
3448
+ this.featuredAsset = asset;
3449
+ this.emitChangeEvent(this.assets, asset);
3450
+ };
3451
+ AssetsComponent.prototype.isFeatured = function (asset) {
3452
+ return !!this.featuredAsset && this.featuredAsset.id === asset.id;
3453
+ };
3454
+ AssetsComponent.prototype.previewAsset = function (asset) {
3455
+ this.modalService
3456
+ .fromComponent(i2.AssetPreviewDialogComponent, {
3457
+ size: 'xl',
3458
+ closable: true,
3459
+ locals: { asset: asset },
3460
+ })
3461
+ .subscribe();
3462
+ };
3463
+ AssetsComponent.prototype.removeAsset = function (asset) {
3464
+ this.assets = this.assets.filter(function (a) { return a.id !== asset.id; });
3465
+ if (this.featuredAsset && this.featuredAsset.id === asset.id) {
3466
+ this.featuredAsset = this.assets.length > 0 ? this.assets[0] : undefined;
3467
+ }
3468
+ this.emitChangeEvent(this.assets, this.featuredAsset);
3469
+ };
3470
+ AssetsComponent.prototype.emitChangeEvent = function (assets, featuredAsset) {
3471
+ this.change.emit({
3472
+ assets: assets,
3473
+ featuredAsset: featuredAsset,
3474
+ });
3475
+ };
3476
+ AssetsComponent.prototype.dropListDropped = function (event) {
3477
+ dragDrop.moveItemInArray(this.assets, event.previousContainer.data, event.container.data);
3478
+ this.emitChangeEvent(this.assets, this.featuredAsset);
3479
+ };
3480
+ return AssetsComponent;
3481
+ }());
3482
+ AssetsComponent.decorators = [
3483
+ { type: i0.Component, args: [{
3484
+ selector: 'vdr-assets',
3485
+ template: "<div class=\"card\" *ngIf=\"!compact; else compactView\">\r\n <div class=\"card-img\">\r\n <div class=\"featured-asset\">\r\n <img\r\n *ngIf=\"featuredAsset\"\r\n [src]=\"featuredAsset | assetPreview:'small'\"\r\n (click)=\"previewAsset(featuredAsset)\"\r\n />\r\n <div class=\"placeholder\" *ngIf=\"!featuredAsset\" (click)=\"selectAssets()\">\r\n <clr-icon shape=\"image\" size=\"128\"></clr-icon>\r\n <div>{{ 'catalog.no-featured-asset' | translate }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-block\"><ng-container *ngTemplateOutlet=\"assetList\"></ng-container></div>\r\n <div class=\"card-footer\" *vdrIfPermissions=\"updatePermissions\">\r\n <button class=\"btn\" (click)=\"selectAssets()\">\r\n <clr-icon shape=\"attachment\"></clr-icon>\r\n {{ 'asset.add-asset' | translate }}\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<ng-template #compactView>\r\n <div class=\"featured-asset compact\">\r\n <img\r\n *ngIf=\"featuredAsset\"\r\n [src]=\"featuredAsset | assetPreview:'thumb'\"\r\n (click)=\"previewAsset(featuredAsset)\"\r\n />\r\n\r\n <div class=\"placeholder\" *ngIf=\"!featuredAsset\" (click)=\"selectAssets()\"><clr-icon shape=\"image\" size=\"150\"></clr-icon></div>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"assetList\"></ng-container>\r\n <button\r\n *vdrIfPermissions=\"updatePermissions\"\r\n class=\"compact-select btn btn-icon btn-sm btn-block\"\r\n [title]=\"'asset.add-asset' | translate\"\r\n (click)=\"selectAssets()\"\r\n >\r\n <clr-icon shape=\"attachment\"></clr-icon>\r\n {{ 'asset.add-asset' | translate }}\r\n </button>\r\n</ng-template>\r\n\r\n<ng-template #assetList>\r\n <div class=\"all-assets\" [class.compact]=\"compact\" cdkDropListGroup>\r\n <div\r\n *ngFor=\"let asset of assets; let index = index\"\r\n class=\"drop-list\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListData]=\"index\"\r\n [cdkDropListDisabled]=\"!(updatePermissions | hasPermission)\"\r\n (cdkDropListDropped)=\"dropListDropped($event)\"\r\n >\r\n <vdr-dropdown cdkDrag>\r\n <div\r\n class=\"asset-thumb\"\r\n vdrDropdownTrigger\r\n [class.featured]=\"isFeatured(asset)\"\r\n [title]=\"\"\r\n tabindex=\"0\"\r\n >\r\n <img [src]=\"asset | assetPreview:'tiny'\" />\r\n </div>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n <button type=\"button\" vdrDropdownItem (click)=\"previewAsset(asset)\">\r\n {{ 'asset.preview' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isFeatured(asset) || !(updatePermissions | hasPermission)\"\r\n vdrDropdownItem\r\n (click)=\"setAsFeatured(asset)\"\r\n >\r\n {{ 'asset.set-as-featured-asset' | translate }}\r\n </button>\r\n <div class=\"dropdown-divider\"></div>\r\n <button\r\n type=\"button\"\r\n class=\"remove-asset\"\r\n vdrDropdownItem\r\n [disabled]=\"!(updatePermissions | hasPermission)\"\r\n (click)=\"removeAsset(asset)\"\r\n >\r\n {{ 'asset.remove-asset' | translate }}\r\n </button>\r\n </vdr-dropdown-menu>\r\n </vdr-dropdown>\r\n </div>\r\n </div>\r\n</ng-template>\r\n",
3486
+ changeDetection: i0.ChangeDetectionStrategy.OnPush,
3487
+ styles: [":host{width:340px;display:block}:host.compact{width:162px}.placeholder{text-align:center;color:var(--color-grey-300)}.featured-asset{text-align:center;background:var(--color-component-bg-200);padding:6px;cursor:pointer}.featured-asset.compact{width:100%;min-height:40px;position:relative;padding:6px}.featured-asset .compact-select{position:absolute;bottom:6px;right:6px;margin:0}.all-assets{display:flex;flex-wrap:wrap}.all-assets .drop-list{min-width:60px}.all-assets .asset-thumb{margin:3px;padding:0;border:2px solid var(--color-component-border-100);cursor:pointer}.all-assets .asset-thumb.featured{border-color:var(--color-primary-500)}.all-assets .remove-asset{color:var(--color-warning-500)}.all-assets.compact .drop-list{min-width:54px}.all-assets.compact .asset-thumb{margin:1px;border-width:1px}.all-assets.compact .cdk-drag-placeholder{width:50px}.all-assets.compact .cdk-drag-placeholder .asset-thumb{width:50px}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.all-assets.cdk-drop-list-dragging vdr-dropdown:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging>*:not(.cdk-drag-placeholder){display:none}\n"]
3488
+ },] }
3489
+ ];
3490
+ AssetsComponent.ctorParameters = function () { return [
3491
+ { type: i2.ModalService },
3492
+ { type: i0.ChangeDetectorRef }
3493
+ ]; };
3494
+ AssetsComponent.propDecorators = {
3495
+ assetsSetter: [{ type: i0.Input, args: ['assets',] }],
3496
+ featuredAsset: [{ type: i0.Input }],
3497
+ compact: [{ type: i0.HostBinding, args: ['class.compact',] }, { type: i0.Input }],
3498
+ change: [{ type: i0.Output }],
3499
+ updatePermissions: [{ type: i0.Input }]
3500
+ };
3501
+
3366
3502
  var CollectionContentsComponent = /** @class */ (function () {
3367
3503
  function CollectionContentsComponent(route, router, dataService) {
3368
3504
  this.route = route;
@@ -3855,118 +3991,6 @@
3855
3991
  textArea: [{ type: i0.ViewChild, args: ['textArea', { static: true },] }]
3856
3992
  };
3857
3993
 
3858
- /**
3859
- * A component which displays the Assets associated with a product, and allows assets to be removed and
3860
- * added, and for the featured asset to be set.
3861
- *
3862
- * Note: rather complex code for drag drop is due to a limitation of the default CDK implementation
3863
- * which is addressed by a work-around from here: https://github.com/angular/components/issues/13372#issuecomment-483998378
3864
- */
3865
- var ProductAssetsComponent = /** @class */ (function () {
3866
- function ProductAssetsComponent(modalService, changeDetector, viewportRuler, collectionDetailComponent) {
3867
- this.modalService = modalService;
3868
- this.changeDetector = changeDetector;
3869
- this.viewportRuler = viewportRuler;
3870
- this.collectionDetailComponent = collectionDetailComponent;
3871
- this.compact = false;
3872
- this.change = new i0.EventEmitter();
3873
- this.assets = [];
3874
- this.updateCollectionPermissions = [i2.Permission.UpdateCatalog, i2.Permission.UpdateCollection];
3875
- this.updateProductPermissions = [i2.Permission.UpdateCatalog, i2.Permission.UpdateProduct];
3876
- }
3877
- Object.defineProperty(ProductAssetsComponent.prototype, "assetsSetter", {
3878
- set: function (val) {
3879
- // create a new non-readonly array of assets
3880
- this.assets = (val || []).slice();
3881
- },
3882
- enumerable: false,
3883
- configurable: true
3884
- });
3885
- Object.defineProperty(ProductAssetsComponent.prototype, "updatePermissions", {
3886
- get: function () {
3887
- if (this.collectionDetailComponent) {
3888
- return this.updateCollectionPermissions;
3889
- }
3890
- else {
3891
- return this.updateProductPermissions;
3892
- }
3893
- },
3894
- enumerable: false,
3895
- configurable: true
3896
- });
3897
- ProductAssetsComponent.prototype.selectAssets = function () {
3898
- var _this = this;
3899
- this.modalService
3900
- .fromComponent(i2.AssetPickerDialogComponent, {
3901
- size: 'xl',
3902
- })
3903
- .subscribe(function (result) {
3904
- if (result && result.length) {
3905
- _this.assets = unique.unique(_this.assets.concat(result), 'id');
3906
- if (!_this.featuredAsset) {
3907
- _this.featuredAsset = result[0];
3908
- }
3909
- _this.emitChangeEvent(_this.assets, _this.featuredAsset);
3910
- _this.changeDetector.markForCheck();
3911
- }
3912
- });
3913
- };
3914
- ProductAssetsComponent.prototype.setAsFeatured = function (asset) {
3915
- this.featuredAsset = asset;
3916
- this.emitChangeEvent(this.assets, asset);
3917
- };
3918
- ProductAssetsComponent.prototype.isFeatured = function (asset) {
3919
- return !!this.featuredAsset && this.featuredAsset.id === asset.id;
3920
- };
3921
- ProductAssetsComponent.prototype.previewAsset = function (asset) {
3922
- this.modalService
3923
- .fromComponent(i2.AssetPreviewDialogComponent, {
3924
- size: 'xl',
3925
- closable: true,
3926
- locals: { asset: asset },
3927
- })
3928
- .subscribe();
3929
- };
3930
- ProductAssetsComponent.prototype.removeAsset = function (asset) {
3931
- this.assets = this.assets.filter(function (a) { return a.id !== asset.id; });
3932
- if (this.featuredAsset && this.featuredAsset.id === asset.id) {
3933
- this.featuredAsset = this.assets.length > 0 ? this.assets[0] : undefined;
3934
- }
3935
- this.emitChangeEvent(this.assets, this.featuredAsset);
3936
- };
3937
- ProductAssetsComponent.prototype.emitChangeEvent = function (assets, featuredAsset) {
3938
- this.change.emit({
3939
- assets: assets,
3940
- featuredAsset: featuredAsset,
3941
- });
3942
- };
3943
- ProductAssetsComponent.prototype.dropListDropped = function (event) {
3944
- dragDrop.moveItemInArray(this.assets, event.previousContainer.data, event.container.data);
3945
- this.emitChangeEvent(this.assets, this.featuredAsset);
3946
- };
3947
- return ProductAssetsComponent;
3948
- }());
3949
- ProductAssetsComponent.decorators = [
3950
- { type: i0.Component, args: [{
3951
- selector: 'vdr-product-assets',
3952
- template: "<div class=\"card\" *ngIf=\"!compact; else compactView\">\r\n <div class=\"card-img\">\r\n <div class=\"featured-asset\">\r\n <img\r\n *ngIf=\"featuredAsset\"\r\n [src]=\"featuredAsset | assetPreview:'small'\"\r\n (click)=\"previewAsset(featuredAsset)\"\r\n />\r\n <div class=\"placeholder\" *ngIf=\"!featuredAsset\" (click)=\"selectAssets()\">\r\n <clr-icon shape=\"image\" size=\"128\"></clr-icon>\r\n <div>{{ 'catalog.no-featured-asset' | translate }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-block\"><ng-container *ngTemplateOutlet=\"assetList\"></ng-container></div>\r\n <div class=\"card-footer\" *vdrIfPermissions=\"updatePermissions\">\r\n <button class=\"btn\" (click)=\"selectAssets()\">\r\n <clr-icon shape=\"attachment\"></clr-icon>\r\n {{ 'asset.add-asset' | translate }}\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<ng-template #compactView>\r\n <div class=\"featured-asset compact\">\r\n <img\r\n *ngIf=\"featuredAsset\"\r\n [src]=\"featuredAsset | assetPreview:'thumb'\"\r\n (click)=\"previewAsset(featuredAsset)\"\r\n />\r\n\r\n <div class=\"placeholder\" *ngIf=\"!featuredAsset\" (click)=\"selectAssets()\"><clr-icon shape=\"image\" size=\"150\"></clr-icon></div>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"assetList\"></ng-container>\r\n <button\r\n *vdrIfPermissions=\"updatePermissions\"\r\n class=\"compact-select btn btn-icon btn-sm btn-block\"\r\n [title]=\"'asset.add-asset' | translate\"\r\n (click)=\"selectAssets()\"\r\n >\r\n <clr-icon shape=\"attachment\"></clr-icon>\r\n {{ 'asset.add-asset' | translate }}\r\n </button>\r\n</ng-template>\r\n\r\n<ng-template #assetList>\r\n <div class=\"all-assets\" [class.compact]=\"compact\" cdkDropListGroup>\r\n <div\r\n *ngFor=\"let asset of assets; let index = index\"\r\n class=\"drop-list\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListData]=\"index\"\r\n [cdkDropListDisabled]=\"!(updatePermissions | hasPermission)\"\r\n (cdkDropListDropped)=\"dropListDropped($event)\"\r\n >\r\n <vdr-dropdown cdkDrag>\r\n <div\r\n class=\"asset-thumb\"\r\n vdrDropdownTrigger\r\n [class.featured]=\"isFeatured(asset)\"\r\n [title]=\"\"\r\n tabindex=\"0\"\r\n >\r\n <img [src]=\"asset | assetPreview:'tiny'\" />\r\n </div>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n <button type=\"button\" vdrDropdownItem (click)=\"previewAsset(asset)\">\r\n {{ 'asset.preview' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isFeatured(asset) || !(updatePermissions | hasPermission)\"\r\n vdrDropdownItem\r\n (click)=\"setAsFeatured(asset)\"\r\n >\r\n {{ 'asset.set-as-featured-asset' | translate }}\r\n </button>\r\n <div class=\"dropdown-divider\"></div>\r\n <button\r\n type=\"button\"\r\n class=\"remove-asset\"\r\n vdrDropdownItem\r\n [disabled]=\"!(updatePermissions | hasPermission)\"\r\n (click)=\"removeAsset(asset)\"\r\n >\r\n {{ 'asset.remove-asset' | translate }}\r\n </button>\r\n </vdr-dropdown-menu>\r\n </vdr-dropdown>\r\n </div>\r\n </div>\r\n</ng-template>\r\n",
3953
- changeDetection: i0.ChangeDetectionStrategy.OnPush,
3954
- styles: [":host{width:340px;display:block}:host.compact{width:162px}.placeholder{text-align:center;color:var(--color-grey-300)}.featured-asset{text-align:center;background:var(--color-component-bg-200);padding:6px;cursor:pointer}.featured-asset.compact{width:100%;min-height:40px;position:relative;padding:6px}.featured-asset .compact-select{position:absolute;bottom:6px;right:6px;margin:0}.all-assets{display:flex;flex-wrap:wrap}.all-assets .drop-list{min-width:60px}.all-assets .asset-thumb{margin:3px;padding:0;border:2px solid var(--color-component-border-100);cursor:pointer}.all-assets .asset-thumb.featured{border-color:var(--color-primary-500)}.all-assets .remove-asset{color:var(--color-warning-500)}.all-assets.compact .drop-list{min-width:54px}.all-assets.compact .asset-thumb{margin:1px;border-width:1px}.all-assets.compact .cdk-drag-placeholder{width:50px}.all-assets.compact .cdk-drag-placeholder .asset-thumb{width:50px}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.all-assets.cdk-drop-list-dragging vdr-dropdown:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging>*:not(.cdk-drag-placeholder){display:none}\n"]
3955
- },] }
3956
- ];
3957
- ProductAssetsComponent.ctorParameters = function () { return [
3958
- { type: i2.ModalService },
3959
- { type: i0.ChangeDetectorRef },
3960
- { type: overlay.ViewportRuler },
3961
- { type: CollectionDetailComponent, decorators: [{ type: i0.Optional }] }
3962
- ]; };
3963
- ProductAssetsComponent.propDecorators = {
3964
- assetsSetter: [{ type: i0.Input, args: ['assets',] }],
3965
- featuredAsset: [{ type: i0.Input }],
3966
- compact: [{ type: i0.HostBinding, args: ['class.compact',] }, { type: i0.Input }],
3967
- change: [{ type: i0.Output }]
3968
- };
3969
-
3970
3994
  var ɵ0 = i2.SingleSearchSelectionModelFactory;
3971
3995
  var ProductSearchInputComponent = /** @class */ (function () {
3972
3996
  function ProductSearchInputComponent() {
@@ -4159,8 +4183,8 @@
4159
4183
  }
4160
4184
  ProductVariantsListComponent.prototype.ngOnInit = function () {
4161
4185
  var _this = this;
4162
- this.dataService.settings.getGlobalSettings('cache-first').single$.subscribe(function (_b) {
4163
- var globalSettings = _b.globalSettings;
4186
+ this.dataService.settings.getGlobalSettings('cache-first').single$.subscribe(function (_c) {
4187
+ var globalSettings = _c.globalSettings;
4164
4188
  _this.globalTrackInventory = globalSettings.trackInventory;
4165
4189
  _this.globalOutOfStockThreshold = globalSettings.outOfStockThreshold;
4166
4190
  _this.changeDetector.markForCheck();
@@ -4203,6 +4227,13 @@
4203
4227
  }
4204
4228
  return '';
4205
4229
  };
4230
+ ProductVariantsListComponent.prototype.getStockOnHandMinValue = function (variant) {
4231
+ var _a, _b;
4232
+ var effectiveOutOfStockThreshold = ((_a = variant.get('useGlobalOutOfStockThreshold')) === null || _a === void 0 ? void 0 : _a.value)
4233
+ ? this.globalOutOfStockThreshold
4234
+ : (_b = variant.get('outOfStockThreshold')) === null || _b === void 0 ? void 0 : _b.value;
4235
+ return effectiveOutOfStockThreshold;
4236
+ };
4206
4237
  ProductVariantsListComponent.prototype.getSaleableStockLevel = function (variant) {
4207
4238
  var effectiveOutOfStockThreshold = variant.useGlobalOutOfStockThreshold
4208
4239
  ? this.globalOutOfStockThreshold
@@ -4303,18 +4334,18 @@
4303
4334
  });
4304
4335
  };
4305
4336
  ProductVariantsListComponent.prototype.buildFormGroupMap = function () {
4306
- var e_1, _b;
4337
+ var e_1, _c;
4307
4338
  this.formGroupMap.clear();
4308
4339
  try {
4309
- for (var _c = __values(this.formArray.controls), _d = _c.next(); !_d.done; _d = _c.next()) {
4310
- var controlGroup = _d.value;
4340
+ for (var _d = __values(this.formArray.controls), _e = _d.next(); !_e.done; _e = _d.next()) {
4341
+ var controlGroup = _e.value;
4311
4342
  this.formGroupMap.set(controlGroup.value.id, controlGroup);
4312
4343
  }
4313
4344
  }
4314
4345
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
4315
4346
  finally {
4316
4347
  try {
4317
- if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
4348
+ if (_e && !_e.done && (_c = _d.return)) _c.call(_d);
4318
4349
  }
4319
4350
  finally { if (e_1) throw e_1.error; }
4320
4351
  }
@@ -4330,7 +4361,7 @@
4330
4361
  ProductVariantsListComponent.decorators = [
4331
4362
  { type: i0.Component, args: [{
4332
4363
  selector: 'vdr-product-variants-list',
4333
- template: "<div class=\"variants-list\">\r\n <div\r\n class=\"variant-container card\"\r\n *ngFor=\"\r\n let variant of variants | paginate: paginationConfig || { itemsPerPage: 10, currentPage: 1 };\r\n trackBy: trackById;\r\n let i = index\r\n \"\r\n [class.disabled]=\"!formGroupMap.get(variant.id)?.get('enabled')?.value\"\r\n >\r\n <ng-container *ngIf=\"formGroupMap.get(variant.id) as formGroup\" [formGroup]=\"formGroup\">\r\n <div class=\"card-block header-row\">\r\n <div class=\"details\">\r\n <vdr-title-input class=\"sku\" [readonly]=\"!(updatePermission | hasPermission)\">\r\n <clr-input-container>\r\n <input\r\n clrInput\r\n type=\"text\"\r\n formControlName=\"sku\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n [placeholder]=\"'catalog.sku' | translate\"\r\n />\r\n </clr-input-container>\r\n </vdr-title-input>\r\n <vdr-title-input class=\"name\" [readonly]=\"!(updatePermission | hasPermission)\">\r\n <clr-input-container>\r\n <input\r\n clrInput\r\n type=\"text\"\r\n formControlName=\"name\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n [placeholder]=\"'common.name' | translate\"\r\n />\r\n </clr-input-container>\r\n </vdr-title-input>\r\n </div>\r\n <div class=\"right-controls\">\r\n <clr-toggle-wrapper *vdrIfPermissions=\"updatePermission\">\r\n <input type=\"checkbox\" clrToggle name=\"enabled\" formControlName=\"enabled\" />\r\n <label>{{ 'common.enabled' | translate }}</label>\r\n </clr-toggle-wrapper>\r\n </div>\r\n </div>\r\n <div class=\"card-block\">\r\n <div class=\"variant-body\">\r\n <div class=\"assets\">\r\n <vdr-product-assets\r\n [compact]=\"true\"\r\n [assets]=\"pendingAssetChanges[variant.id]?.assets || variant.assets\"\r\n [featuredAsset]=\"\r\n pendingAssetChanges[variant.id]?.featuredAsset || variant.featuredAsset\r\n \"\r\n (change)=\"onAssetChange(variant.id, $event)\"\r\n ></vdr-product-assets>\r\n </div>\r\n <div class=\"variant-form-inputs\">\r\n <div class=\"standard-fields\">\r\n <div class=\"variant-form-input-row\">\r\n <div class=\"tax-category\">\r\n <clr-select-container\r\n *vdrIfPermissions=\"updatePermission; else taxCategoryLabel\"\r\n >\r\n <label>{{ 'catalog.tax-category' | translate }}</label>\r\n <select clrSelect name=\"options\" formControlName=\"taxCategoryId\">\r\n <option\r\n *ngFor=\"let taxCategory of taxCategories\"\r\n [value]=\"taxCategory.id\"\r\n >\r\n {{ taxCategory.name }}\r\n </option>\r\n </select>\r\n </clr-select-container>\r\n <ng-template #taxCategoryLabel>\r\n <label class=\"clr-control-label\">{{\r\n 'catalog.tax-category' | translate\r\n }}</label>\r\n <div class=\"tax-category-label\">\r\n {{ getTaxCategoryName(formGroup) }}\r\n </div>\r\n </ng-template>\r\n </div>\r\n <div class=\"price\">\r\n <clr-input-container>\r\n <label>{{ 'catalog.price' | translate }}</label>\r\n <vdr-currency-input\r\n *ngIf=\"!channelPriceIncludesTax\"\r\n clrInput\r\n [currencyCode]=\"variant.currencyCode\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n formControlName=\"price\"\r\n ></vdr-currency-input>\r\n <vdr-currency-input\r\n *ngIf=\"channelPriceIncludesTax\"\r\n clrInput\r\n [currencyCode]=\"variant.currencyCode\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n formControlName=\"priceWithTax\"\r\n ></vdr-currency-input>\r\n </clr-input-container>\r\n </div>\r\n <vdr-variant-price-detail\r\n [price]=\"formGroup.get('price')!.value\"\r\n [currencyCode]=\"variant.currencyCode\"\r\n [priceIncludesTax]=\"channelPriceIncludesTax\"\r\n [taxCategoryId]=\"formGroup.get('taxCategoryId')!.value\"\r\n ></vdr-variant-price-detail>\r\n </div>\r\n <div class=\"variant-form-input-row\">\r\n <clr-select-container *vdrIfPermissions=\"updatePermission\">\r\n <label\r\n >{{ 'catalog.track-inventory' | translate }}\r\n <vdr-help-tooltip\r\n [content]=\"'catalog.track-inventory-tooltip' | translate\"\r\n ></vdr-help-tooltip>\r\n </label>\r\n <select clrSelect name=\"options\" formControlName=\"trackInventory\">\r\n <option [value]=\"GlobalFlag.TRUE\">\r\n {{ 'catalog.track-inventory-true' | translate }}\r\n </option>\r\n <option [value]=\"GlobalFlag.FALSE\">\r\n {{ 'catalog.track-inventory-false' | translate }}\r\n </option>\r\n <option [value]=\"GlobalFlag.INHERIT\">\r\n {{ 'catalog.track-inventory-inherit' | translate }}\r\n </option>\r\n </select>\r\n </clr-select-container>\r\n <clr-input-container>\r\n <label\r\n >{{ 'catalog.stock-on-hand' | translate }}\r\n <vdr-help-tooltip\r\n [content]=\"'catalog.stock-on-hand-tooltip' | translate\"\r\n ></vdr-help-tooltip\r\n ></label>\r\n <input\r\n [class.inventory-untracked]=\"inventoryIsNotTracked(formGroup)\"\r\n clrInput\r\n type=\"number\"\r\n min=\"0\"\r\n step=\"1\"\r\n formControlName=\"stockOnHand\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n [vdrDisabled]=\"inventoryIsNotTracked(formGroup)\"\r\n />\r\n </clr-input-container>\r\n <div [class.inventory-untracked]=\"inventoryIsNotTracked(formGroup)\">\r\n <label class=\"clr-control-label\"\r\n >{{ 'catalog.stock-allocated' | translate }}\r\n <vdr-help-tooltip\r\n [content]=\"'catalog.stock-allocated-tooltip' | translate\"\r\n ></vdr-help-tooltip\r\n ></label>\r\n <div class=\"value\">\r\n {{ variant.stockAllocated }}\r\n </div>\r\n </div>\r\n <div [class.inventory-untracked]=\"inventoryIsNotTracked(formGroup)\">\r\n <label class=\"clr-control-label\"\r\n >{{ 'catalog.stock-saleable' | translate }}\r\n <vdr-help-tooltip\r\n [content]=\"'catalog.stock-saleable-tooltip' | translate\"\r\n ></vdr-help-tooltip\r\n ></label>\r\n <div class=\"value\">\r\n {{ getSaleableStockLevel(variant) }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"variant-form-input-row\">\r\n <div\r\n class=\"out-of-stock-threshold-wrapper\"\r\n [class.inventory-untracked]=\"inventoryIsNotTracked(formGroup)\"\r\n >\r\n <label class=\"clr-control-label\"\r\n >{{ 'catalog.out-of-stock-threshold' | translate\r\n }}<vdr-help-tooltip\r\n [content]=\"'catalog.out-of-stock-threshold-tooltip' | translate\"\r\n ></vdr-help-tooltip\r\n ></label>\r\n <div class=\"flex\">\r\n <clr-input-container>\r\n <input\r\n clrInput\r\n type=\"number\"\r\n [formControl]=\"formGroup.get('outOfStockThreshold')\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n [vdrDisabled]=\"\r\n formGroup.get('useGlobalOutOfStockThreshold')?.value !==\r\n false || inventoryIsNotTracked(formGroup)\r\n \"\r\n />\r\n </clr-input-container>\r\n <clr-toggle-wrapper>\r\n <input\r\n type=\"checkbox\"\r\n clrToggle\r\n name=\"useGlobalOutOfStockThreshold\"\r\n formControlName=\"useGlobalOutOfStockThreshold\"\r\n [vdrDisabled]=\"\r\n !(updatePermission | hasPermission) ||\r\n inventoryIsNotTracked(formGroup)\r\n \"\r\n />\r\n <label\r\n >{{ 'catalog.use-global-value' | translate }} ({{\r\n globalOutOfStockThreshold\r\n }})</label\r\n >\r\n </clr-toggle-wrapper>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"custom-fields\">\r\n <div class=\"variant-form-input-row\">\r\n <section formGroupName=\"customFields\" *ngIf=\"customFields.length\">\r\n <vdr-tabbed-custom-fields\r\n entityName=\"ProductVariant\"\r\n [customFields]=\"customFields\"\r\n [compact]=\"true\"\r\n [customFieldsFormGroup]=\"formGroup.get('customFields')\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n ></vdr-tabbed-custom-fields>\r\n </section>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-block\">\r\n <div class=\"options-facets\">\r\n <vdr-entity-info [entity]=\"variant\"></vdr-entity-info>\r\n <div *ngIf=\"variant.options.length\">\r\n <div class=\"options\">\r\n <vdr-chip\r\n *ngFor=\"let option of variant.options | sort: 'groupId'\"\r\n [colorFrom]=\"optionGroupName(option.groupId)\"\r\n [invert]=\"true\"\r\n (iconClick)=\"editOption(option)\"\r\n [icon]=\"(updatePermission | hasPermission) && 'pencil'\"\r\n >\r\n <span class=\"option-group-name\">{{ optionGroupName(option.groupId) }}</span>\r\n {{ optionName(option) }}\r\n </vdr-chip>\r\n <a [routerLink]=\"['./', 'options']\" class=\"btn btn-link btn-sm\"\r\n >{{ 'catalog.edit-options' | translate }}...</a\r\n >\r\n </div>\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <div class=\"facets\">\r\n <vdr-facet-value-chip\r\n *ngFor=\"let facetValue of existingFacetValues(variant)\"\r\n [facetValue]=\"facetValue\"\r\n [removable]=\"updatePermission | hasPermission\"\r\n (remove)=\"removeFacetValue(variant, facetValue.id)\"\r\n ></vdr-facet-value-chip>\r\n <vdr-facet-value-chip\r\n *ngFor=\"let facetValue of pendingFacetValues(variant)\"\r\n [facetValue]=\"facetValue\"\r\n [removable]=\"updatePermission | hasPermission\"\r\n (remove)=\"removeFacetValue(variant, facetValue.id)\"\r\n ></vdr-facet-value-chip>\r\n <button\r\n *vdrIfPermissions=\"updatePermission\"\r\n class=\"btn btn-sm btn-secondary\"\r\n (click)=\"selectFacetValueClick.emit([variant.id])\"\r\n >\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.add-facets' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <ng-container *vdrIfMultichannel>\r\n <div class=\"card-block\" *vdrIfDefaultChannelActive>\r\n <div class=\"flex channel-assignment\">\r\n <ng-container *ngFor=\"let channel of variant.channels\">\r\n <vdr-chip\r\n *ngIf=\"!isDefaultChannel(channel.code)\"\r\n icon=\"times-circle\"\r\n [title]=\"'catalog.remove-from-channel' | translate\"\r\n (iconClick)=\"\r\n removeFromChannel.emit({ channelId: channel.id, variant: variant })\r\n \"\r\n >\r\n <vdr-channel-badge [channelCode]=\"channel.code\"></vdr-channel-badge>\r\n {{ channel.code | channelCodeToLabel }}\r\n </vdr-chip>\r\n </ng-container>\r\n <button class=\"btn btn-sm\" (click)=\"assignToChannel.emit(variant)\">\r\n <clr-icon shape=\"layers\"></clr-icon>\r\n {{ 'catalog.assign-to-channel' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n</div>\r\n",
4364
+ template: "<div class=\"variants-list\">\r\n <div\r\n class=\"variant-container card\"\r\n *ngFor=\"\r\n let variant of variants | paginate: paginationConfig || { itemsPerPage: 10, currentPage: 1 };\r\n trackBy: trackById;\r\n let i = index\r\n \"\r\n [class.disabled]=\"!formGroupMap.get(variant.id)?.get('enabled')?.value\"\r\n >\r\n <ng-container *ngIf=\"formGroupMap.get(variant.id) as formGroup\" [formGroup]=\"formGroup\">\r\n <div class=\"card-block header-row\">\r\n <div class=\"details\">\r\n <vdr-title-input class=\"sku\" [readonly]=\"!(updatePermission | hasPermission)\">\r\n <clr-input-container>\r\n <input\r\n clrInput\r\n type=\"text\"\r\n formControlName=\"sku\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n [placeholder]=\"'catalog.sku' | translate\"\r\n />\r\n </clr-input-container>\r\n </vdr-title-input>\r\n <vdr-title-input class=\"name\" [readonly]=\"!(updatePermission | hasPermission)\">\r\n <clr-input-container>\r\n <input\r\n clrInput\r\n type=\"text\"\r\n formControlName=\"name\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n [placeholder]=\"'common.name' | translate\"\r\n />\r\n </clr-input-container>\r\n </vdr-title-input>\r\n </div>\r\n <div class=\"right-controls\">\r\n <clr-toggle-wrapper *vdrIfPermissions=\"updatePermission\">\r\n <input type=\"checkbox\" clrToggle name=\"enabled\" formControlName=\"enabled\" />\r\n <label>{{ 'common.enabled' | translate }}</label>\r\n </clr-toggle-wrapper>\r\n </div>\r\n </div>\r\n <div class=\"card-block\">\r\n <div class=\"variant-body\">\r\n <div class=\"assets\">\r\n <vdr-assets\r\n [compact]=\"true\"\r\n [assets]=\"pendingAssetChanges[variant.id]?.assets || variant.assets\"\r\n [featuredAsset]=\"\r\n pendingAssetChanges[variant.id]?.featuredAsset || variant.featuredAsset\r\n \"\r\n [updatePermissions]=\"updatePermission\"\r\n (change)=\"onAssetChange(variant.id, $event)\"\r\n ></vdr-assets>\r\n </div>\r\n <div class=\"variant-form-inputs\">\r\n <div class=\"standard-fields\">\r\n <div class=\"variant-form-input-row\">\r\n <div class=\"tax-category\">\r\n <clr-select-container\r\n *vdrIfPermissions=\"updatePermission; else taxCategoryLabel\"\r\n >\r\n <label>{{ 'catalog.tax-category' | translate }}</label>\r\n <select clrSelect name=\"options\" formControlName=\"taxCategoryId\">\r\n <option\r\n *ngFor=\"let taxCategory of taxCategories\"\r\n [value]=\"taxCategory.id\"\r\n >\r\n {{ taxCategory.name }}\r\n </option>\r\n </select>\r\n </clr-select-container>\r\n <ng-template #taxCategoryLabel>\r\n <label class=\"clr-control-label\">{{\r\n 'catalog.tax-category' | translate\r\n }}</label>\r\n <div class=\"tax-category-label\">\r\n {{ getTaxCategoryName(formGroup) }}\r\n </div>\r\n </ng-template>\r\n </div>\r\n <div class=\"price\">\r\n <clr-input-container>\r\n <label>{{ 'catalog.price' | translate }}</label>\r\n <vdr-currency-input\r\n *ngIf=\"!channelPriceIncludesTax\"\r\n clrInput\r\n [currencyCode]=\"variant.currencyCode\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n formControlName=\"price\"\r\n ></vdr-currency-input>\r\n <vdr-currency-input\r\n *ngIf=\"channelPriceIncludesTax\"\r\n clrInput\r\n [currencyCode]=\"variant.currencyCode\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n formControlName=\"priceWithTax\"\r\n ></vdr-currency-input>\r\n </clr-input-container>\r\n </div>\r\n <vdr-variant-price-detail\r\n [price]=\"formGroup.get('price')!.value\"\r\n [currencyCode]=\"variant.currencyCode\"\r\n [priceIncludesTax]=\"channelPriceIncludesTax\"\r\n [taxCategoryId]=\"formGroup.get('taxCategoryId')!.value\"\r\n ></vdr-variant-price-detail>\r\n </div>\r\n <div class=\"variant-form-input-row\">\r\n <clr-select-container *vdrIfPermissions=\"updatePermission\">\r\n <label\r\n >{{ 'catalog.track-inventory' | translate }}\r\n <vdr-help-tooltip\r\n [content]=\"'catalog.track-inventory-tooltip' | translate\"\r\n ></vdr-help-tooltip>\r\n </label>\r\n <select clrSelect name=\"options\" formControlName=\"trackInventory\">\r\n <option [value]=\"GlobalFlag.TRUE\">\r\n {{ 'catalog.track-inventory-true' | translate }}\r\n </option>\r\n <option [value]=\"GlobalFlag.FALSE\">\r\n {{ 'catalog.track-inventory-false' | translate }}\r\n </option>\r\n <option [value]=\"GlobalFlag.INHERIT\">\r\n {{ 'catalog.track-inventory-inherit' | translate }}\r\n </option>\r\n </select>\r\n </clr-select-container>\r\n <clr-input-container>\r\n <label\r\n >{{ 'catalog.stock-on-hand' | translate }}\r\n <vdr-help-tooltip\r\n [content]=\"'catalog.stock-on-hand-tooltip' | translate\"\r\n ></vdr-help-tooltip\r\n ></label>\r\n <input\r\n [class.inventory-untracked]=\"inventoryIsNotTracked(formGroup)\"\r\n clrInput\r\n type=\"number\"\r\n [min]=\"getStockOnHandMinValue(formGroup)\"\r\n step=\"1\"\r\n formControlName=\"stockOnHand\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n [vdrDisabled]=\"inventoryIsNotTracked(formGroup)\"\r\n />\r\n </clr-input-container>\r\n <div [class.inventory-untracked]=\"inventoryIsNotTracked(formGroup)\">\r\n <label class=\"clr-control-label\"\r\n >{{ 'catalog.stock-allocated' | translate }}\r\n <vdr-help-tooltip\r\n [content]=\"'catalog.stock-allocated-tooltip' | translate\"\r\n ></vdr-help-tooltip\r\n ></label>\r\n <div class=\"value\">\r\n {{ variant.stockAllocated }}\r\n </div>\r\n </div>\r\n <div [class.inventory-untracked]=\"inventoryIsNotTracked(formGroup)\">\r\n <label class=\"clr-control-label\"\r\n >{{ 'catalog.stock-saleable' | translate }}\r\n <vdr-help-tooltip\r\n [content]=\"'catalog.stock-saleable-tooltip' | translate\"\r\n ></vdr-help-tooltip\r\n ></label>\r\n <div class=\"value\">\r\n {{ getSaleableStockLevel(variant) }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"variant-form-input-row\">\r\n <div\r\n class=\"out-of-stock-threshold-wrapper\"\r\n [class.inventory-untracked]=\"inventoryIsNotTracked(formGroup)\"\r\n >\r\n <label class=\"clr-control-label\"\r\n >{{ 'catalog.out-of-stock-threshold' | translate\r\n }}<vdr-help-tooltip\r\n [content]=\"'catalog.out-of-stock-threshold-tooltip' | translate\"\r\n ></vdr-help-tooltip\r\n ></label>\r\n <div class=\"flex\">\r\n <clr-input-container>\r\n <input\r\n clrInput\r\n type=\"number\"\r\n [formControl]=\"formGroup.get('outOfStockThreshold')\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n [vdrDisabled]=\"\r\n formGroup.get('useGlobalOutOfStockThreshold')?.value !==\r\n false || inventoryIsNotTracked(formGroup)\r\n \"\r\n />\r\n </clr-input-container>\r\n <clr-toggle-wrapper>\r\n <input\r\n type=\"checkbox\"\r\n clrToggle\r\n name=\"useGlobalOutOfStockThreshold\"\r\n formControlName=\"useGlobalOutOfStockThreshold\"\r\n [vdrDisabled]=\"\r\n !(updatePermission | hasPermission) ||\r\n inventoryIsNotTracked(formGroup)\r\n \"\r\n />\r\n <label\r\n >{{ 'catalog.use-global-value' | translate }} ({{\r\n globalOutOfStockThreshold\r\n }})</label\r\n >\r\n </clr-toggle-wrapper>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"custom-fields\">\r\n <div class=\"variant-form-input-row\">\r\n <section formGroupName=\"customFields\" *ngIf=\"customFields.length\">\r\n <vdr-tabbed-custom-fields\r\n entityName=\"ProductVariant\"\r\n [customFields]=\"customFields\"\r\n [compact]=\"true\"\r\n [customFieldsFormGroup]=\"formGroup.get('customFields')\"\r\n [readonly]=\"!(updatePermission | hasPermission)\"\r\n ></vdr-tabbed-custom-fields>\r\n </section>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-block\">\r\n <div class=\"options-facets\">\r\n <vdr-entity-info [entity]=\"variant\"></vdr-entity-info>\r\n <div *ngIf=\"variant.options.length\">\r\n <div class=\"options\">\r\n <vdr-chip\r\n *ngFor=\"let option of variant.options | sort: 'groupId'\"\r\n [colorFrom]=\"optionGroupName(option.groupId)\"\r\n [invert]=\"true\"\r\n (iconClick)=\"editOption(option)\"\r\n [icon]=\"(updatePermission | hasPermission) && 'pencil'\"\r\n >\r\n <span class=\"option-group-name\">{{ optionGroupName(option.groupId) }}</span>\r\n {{ optionName(option) }}\r\n </vdr-chip>\r\n <a [routerLink]=\"['./', 'options']\" class=\"btn btn-link btn-sm\"\r\n >{{ 'catalog.edit-options' | translate }}...</a\r\n >\r\n </div>\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <div class=\"facets\">\r\n <vdr-facet-value-chip\r\n *ngFor=\"let facetValue of existingFacetValues(variant)\"\r\n [facetValue]=\"facetValue\"\r\n [removable]=\"updatePermission | hasPermission\"\r\n (remove)=\"removeFacetValue(variant, facetValue.id)\"\r\n ></vdr-facet-value-chip>\r\n <vdr-facet-value-chip\r\n *ngFor=\"let facetValue of pendingFacetValues(variant)\"\r\n [facetValue]=\"facetValue\"\r\n [removable]=\"updatePermission | hasPermission\"\r\n (remove)=\"removeFacetValue(variant, facetValue.id)\"\r\n ></vdr-facet-value-chip>\r\n <button\r\n *vdrIfPermissions=\"updatePermission\"\r\n class=\"btn btn-sm btn-secondary\"\r\n (click)=\"selectFacetValueClick.emit([variant.id])\"\r\n >\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.add-facets' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <ng-container *vdrIfMultichannel>\r\n <div class=\"card-block\" *vdrIfDefaultChannelActive>\r\n <div class=\"flex channel-assignment\">\r\n <ng-container *ngFor=\"let channel of variant.channels\">\r\n <vdr-chip\r\n *ngIf=\"!isDefaultChannel(channel.code)\"\r\n icon=\"times-circle\"\r\n [title]=\"'catalog.remove-from-channel' | translate\"\r\n (iconClick)=\"\r\n removeFromChannel.emit({ channelId: channel.id, variant: variant })\r\n \"\r\n >\r\n <vdr-channel-badge [channelCode]=\"channel.code\"></vdr-channel-badge>\r\n {{ channel.code | channelCodeToLabel }}\r\n </vdr-chip>\r\n </ng-container>\r\n <button class=\"btn btn-sm\" (click)=\"assignToChannel.emit(variant)\">\r\n <clr-icon shape=\"layers\"></clr-icon>\r\n {{ 'catalog.assign-to-channel' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n</div>\r\n",
4334
4365
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
4335
4366
  styles: [".with-selected{display:flex;min-height:52px;align-items:center;border:1px solid var(--color-component-border-100);border-radius:3px;padding:6px 18px}.with-selected vdr-select-toggle{margin-right:12px}.with-selected>label{margin-right:12px}.variant-container{transition:background-color .2s;min-height:330px}.variant-container.disabled{background-color:var(--color-component-bg-200)}.variant-container .header-row{display:flex;align-items:center;flex-wrap:wrap}.variant-container .variant-body{display:flex;flex-direction:column}@media screen and (min-width: 768px){.variant-container .variant-body{flex-direction:row}}.variant-container .details{display:flex;flex-direction:column;flex:1;margin-right:12px}@media screen and (min-width: 768px){.variant-container .details{flex-direction:row;height:36px}}.variant-container .details .name{flex:1}.variant-container .details .name ::ng-deep .clr-control-container{width:100%}.variant-container .details .name ::ng-deep .clr-control-container input.clr-input{min-width:100%}.variant-container .details .sku{width:160px;margin-right:20px;flex:0}.variant-container .details ::ng-deep .name input{min-width:300px}.variant-container .right-controls{display:flex}.variant-container .tax-category-label{margin-top:3px}.variant-container .variant-form-inputs{flex:1;display:flex;flex-direction:column}@media screen and (min-width: 768px){.variant-container .variant-form-inputs{flex-direction:row}}.variant-container .variant-form-input-row{display:flex;flex-wrap:wrap}@media screen and (min-width: 768px){.variant-container .variant-form-input-row{margin:0 6px 8px 24px}}.variant-container .variant-form-input-row>*{margin-right:24px;margin-bottom:24px}.variant-container .track-inventory-toggle{margin-top:22px}.variant-container .clr-form-control{margin-top:0}.variant-container .facets{display:flex;flex-wrap:wrap;align-items:center}.variant-container .pricing{display:flex}.variant-container .pricing>div{margin-right:12px}.variant-container .option-group-name{color:var(--color-text-200);text-transform:uppercase;font-size:10px;margin-right:3px;height:11px}.variant-container .options-facets{display:flex;color:var(--color-grey-400)}.variant-container ::ng-deep .clr-control-container{width:100%}.channel-assignment{justify-content:flex-end}.channel-assignment .btn{margin:6px 12px 6px 0}.out-of-stock-threshold-wrapper{display:flex;flex-direction:column}.out-of-stock-threshold-wrapper clr-toggle-wrapper{margin-left:24px}.inventory-untracked{opacity:.5}\n"]
4336
4367
  },] }
@@ -4504,7 +4535,7 @@
4504
4535
  ProductVariantsListComponent,
4505
4536
  ApplyFacetDialogComponent,
4506
4537
  AssetListComponent,
4507
- ProductAssetsComponent,
4538
+ AssetsComponent,
4508
4539
  VariantPriceDetailComponent,
4509
4540
  CollectionListComponent,
4510
4541
  CollectionDetailComponent,
@@ -4544,6 +4575,7 @@
4544
4575
  exports.AssetDetailComponent = AssetDetailComponent;
4545
4576
  exports.AssetListComponent = AssetListComponent;
4546
4577
  exports.AssetResolver = AssetResolver;
4578
+ exports.AssetsComponent = AssetsComponent;
4547
4579
  exports.AssignProductsToChannelDialogComponent = AssignProductsToChannelDialogComponent;
4548
4580
  exports.CatalogModule = CatalogModule;
4549
4581
  exports.CollectionContentsComponent = CollectionContentsComponent;
@@ -4560,7 +4592,6 @@
4560
4592
  exports.GeneratedVariant = GeneratedVariant;
4561
4593
  exports.OPTION_VALUE_INPUT_VALUE_ACCESSOR = OPTION_VALUE_INPUT_VALUE_ACCESSOR;
4562
4594
  exports.OptionValueInputComponent = OptionValueInputComponent;
4563
- exports.ProductAssetsComponent = ProductAssetsComponent;
4564
4595
  exports.ProductDetailComponent = ProductDetailComponent;
4565
4596
  exports.ProductDetailService = ProductDetailService;
4566
4597
  exports.ProductListComponent = ProductListComponent;