@vendure/admin-ui 1.7.4 → 1.8.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.
- package/bundles/vendure-admin-ui-catalog.umd.js +902 -74
- package/bundles/vendure-admin-ui-catalog.umd.js.map +1 -1
- package/bundles/vendure-admin-ui-core.umd.js +2392 -820
- package/bundles/vendure-admin-ui-core.umd.js.map +1 -1
- package/bundles/vendure-admin-ui-customer.umd.js +4 -3
- package/bundles/vendure-admin-ui-customer.umd.js.map +1 -1
- package/bundles/vendure-admin-ui-dashboard.umd.js +3 -1
- package/bundles/vendure-admin-ui-dashboard.umd.js.map +1 -1
- package/bundles/vendure-admin-ui-order.umd.js +781 -175
- package/bundles/vendure-admin-ui-order.umd.js.map +1 -1
- package/bundles/vendure-admin-ui-settings.umd.js +5 -4
- package/bundles/vendure-admin-ui-settings.umd.js.map +1 -1
- package/bundles/vendure-admin-ui-system.umd.js +1 -1
- package/catalog/catalog.module.d.ts +3 -0
- package/catalog/components/assign-to-channel-dialog/assign-to-channel-dialog.component.d.ts +17 -0
- package/catalog/components/bulk-add-facet-values-dialog/bulk-add-facet-values-dialog.component.d.ts +38 -0
- package/catalog/components/bulk-add-facet-values-dialog/bulk-add-facet-values-dialog.graphql.d.ts +4 -0
- package/catalog/components/collection-list/collection-list-bulk-actions.d.ts +6 -0
- package/catalog/components/collection-list/collection-list.component.d.ts +7 -5
- package/catalog/components/collection-tree/collection-tree-node.component.d.ts +8 -4
- package/catalog/components/collection-tree/collection-tree.component.d.ts +2 -1
- package/catalog/components/facet-list/facet-list-bulk-actions.d.ts +5 -0
- package/catalog/components/facet-list/facet-list.component.d.ts +2 -1
- package/catalog/components/product-list/product-list-bulk-actions.d.ts +6 -0
- package/catalog/components/product-list/product-list.component.d.ts +2 -1
- package/catalog/public_api.d.ts +6 -0
- package/catalog/vendure-admin-ui-catalog.metadata.json +1 -1
- package/core/common/component-registry-types.d.ts +1 -1
- package/core/common/generated-types.d.ts +609 -3
- package/core/common/utilities/bulk-action-utils.d.ts +19 -0
- package/core/common/utilities/selection-manager.d.ts +7 -0
- package/core/common/version.d.ts +1 -1
- package/core/data/definitions/collection-definitions.d.ts +3 -0
- package/core/data/definitions/facet-definitions.d.ts +3 -0
- package/core/data/definitions/order-definitions.d.ts +12 -0
- package/core/data/definitions/product-definitions.d.ts +1 -0
- package/core/data/providers/collection-data.service.d.ts +4 -1
- package/core/data/providers/facet-data.service.d.ts +4 -1
- package/core/data/providers/order-data.service.d.ts +18 -1
- package/core/data/providers/product-data.service.d.ts +1 -0
- package/core/providers/bulk-action-registry/bulk-action-registry.service.d.ts +6 -0
- package/core/providers/bulk-action-registry/bulk-action-types.d.ts +149 -0
- package/core/providers/bulk-action-registry/register-bulk-action.d.ts +53 -0
- package/core/providers/modal/modal.service.d.ts +2 -0
- package/core/providers/nav-builder/nav-builder-types.d.ts +1 -0
- package/core/public_api.d.ts +18 -1
- package/core/shared/components/asset-gallery/asset-gallery.component.d.ts +3 -3
- package/core/shared/components/bulk-action-menu/bulk-action-menu.component.d.ts +29 -0
- package/core/shared/components/data-table/data-table.component.d.ts +26 -7
- package/core/shared/components/dropdown/dropdown-menu.component.d.ts +1 -0
- package/core/shared/components/radio-card/radio-card-fieldset.component.d.ts +21 -0
- package/core/shared/components/radio-card/radio-card.component.d.ts +19 -0
- package/core/shared/components/rich-text-editor/prosemirror/context-menu/context-menu.component.d.ts +28 -0
- package/core/shared/components/rich-text-editor/prosemirror/context-menu/context-menu.service.d.ts +31 -0
- package/core/shared/components/rich-text-editor/prosemirror/custom-nodes.d.ts +4 -0
- package/core/shared/components/rich-text-editor/prosemirror/inputrules.d.ts +5 -5
- package/core/shared/components/rich-text-editor/prosemirror/menu/links.d.ts +1 -1
- package/core/shared/components/rich-text-editor/prosemirror/menu/menu-common.d.ts +12 -0
- package/core/shared/components/rich-text-editor/prosemirror/menu/menu-plugin.d.ts +9 -0
- package/core/shared/components/rich-text-editor/prosemirror/menu/sub-menu-with-icon.d.ts +14 -0
- package/core/shared/components/rich-text-editor/prosemirror/plugins/image-plugin.d.ts +7 -0
- package/core/shared/components/rich-text-editor/prosemirror/plugins/link-select-plugin.d.ts +1 -1
- package/core/shared/components/rich-text-editor/prosemirror/plugins/raw-editor-plugin.d.ts +7 -0
- package/core/shared/components/rich-text-editor/prosemirror/plugins/tables-plugin.d.ts +13 -0
- package/core/shared/components/rich-text-editor/prosemirror/prosemirror.service.d.ts +7 -3
- package/core/shared/components/rich-text-editor/prosemirror/types.d.ts +0 -2
- package/core/shared/components/rich-text-editor/raw-html-dialog/raw-html-dialog.component.d.ts +18 -0
- package/core/shared/components/rich-text-editor/rich-text-editor.component.d.ts +6 -2
- package/core/shared/dynamic-form-inputs/code-editor-form-input/base-code-editor-form-input.component.d.ts +27 -0
- package/core/shared/dynamic-form-inputs/code-editor-form-input/html-editor-form-input.component.d.ts +19 -0
- package/core/shared/dynamic-form-inputs/code-editor-form-input/json-editor-form-input.component.d.ts +5 -17
- package/core/shared/dynamic-form-inputs/register-dynamic-input-components.d.ts +2 -1
- package/core/vendure-admin-ui-core.metadata.json +1 -1
- package/customer/components/customer-group-member-list/customer-group-member-list.component.d.ts +11 -4
- package/customer/vendure-admin-ui-customer.metadata.json +1 -1
- package/esm2015/catalog/catalog.module.js +25 -2
- package/esm2015/catalog/components/assign-products-to-channel-dialog/assign-products-to-channel-dialog.component.js +4 -1
- package/esm2015/catalog/components/assign-to-channel-dialog/assign-to-channel-dialog.component.js +51 -0
- package/esm2015/catalog/components/bulk-add-facet-values-dialog/bulk-add-facet-values-dialog.component.js +89 -0
- package/esm2015/catalog/components/bulk-add-facet-values-dialog/bulk-add-facet-values-dialog.graphql.js +69 -0
- package/esm2015/catalog/components/collection-detail/collection-detail.component.js +3 -3
- package/esm2015/catalog/components/collection-list/collection-list-bulk-actions.js +147 -0
- package/esm2015/catalog/components/collection-list/collection-list.component.js +17 -8
- package/esm2015/catalog/components/collection-tree/collection-tree-node.component.js +16 -7
- package/esm2015/catalog/components/collection-tree/collection-tree.component.js +3 -2
- package/esm2015/catalog/components/facet-list/facet-list-bulk-actions.js +208 -0
- package/esm2015/catalog/components/facet-list/facet-list.component.js +13 -4
- package/esm2015/catalog/components/product-detail/product-detail.component.js +35 -23
- package/esm2015/catalog/components/product-list/product-list-bulk-actions.js +173 -0
- package/esm2015/catalog/components/product-list/product-list.component.js +10 -5
- package/esm2015/catalog/components/product-variants-list/product-variants-list.component.js +2 -2
- package/esm2015/catalog/providers/routing/collection-resolver.js +2 -1
- package/esm2015/catalog/public_api.js +7 -1
- package/esm2015/core/common/component-registry-types.js +1 -1
- package/esm2015/core/common/generated-types.js +5 -1
- package/esm2015/core/common/introspection-result.js +296 -191
- package/esm2015/core/common/utilities/bulk-action-utils.js +44 -0
- package/esm2015/core/common/utilities/selection-manager.js +33 -1
- package/esm2015/core/common/version.js +2 -2
- package/esm2015/core/components/breadcrumb/breadcrumb.component.js +1 -1
- package/esm2015/core/data/definitions/collection-definitions.js +30 -1
- package/esm2015/core/data/definitions/facet-definitions.js +31 -1
- package/esm2015/core/data/definitions/order-definitions.js +114 -1
- package/esm2015/core/data/definitions/product-definitions.js +15 -1
- package/esm2015/core/data/providers/collection-data.service.js +17 -2
- package/esm2015/core/data/providers/customer-data.service.js +8 -4
- package/esm2015/core/data/providers/facet-data.service.js +18 -2
- package/esm2015/core/data/providers/order-data.service.js +38 -2
- package/esm2015/core/data/providers/product-data.service.js +7 -2
- package/esm2015/core/data/utils/remove-readonly-custom-fields.js +5 -1
- package/esm2015/core/providers/bulk-action-registry/bulk-action-registry.service.js +27 -0
- package/esm2015/core/providers/bulk-action-registry/bulk-action-types.js +2 -0
- package/esm2015/core/providers/bulk-action-registry/register-bulk-action.js +63 -0
- package/esm2015/core/providers/dashboard-widget/dashboard-widget.service.js +1 -4
- package/esm2015/core/providers/modal/modal.service.js +2 -1
- package/esm2015/core/providers/nav-builder/nav-builder-types.js +1 -1
- package/esm2015/core/public_api.js +19 -2
- package/esm2015/core/shared/components/action-bar/action-bar.component.js +4 -8
- package/esm2015/core/shared/components/asset-gallery/asset-gallery.component.js +2 -2
- package/esm2015/core/shared/components/bulk-action-menu/bulk-action-menu.component.js +99 -0
- package/esm2015/core/shared/components/data-table/data-table.component.js +64 -15
- package/esm2015/core/shared/components/dropdown/dropdown-menu.component.js +4 -3
- package/esm2015/core/shared/components/facet-value-selector/facet-value-selector.component.js +2 -2
- package/esm2015/core/shared/components/language-selector/language-selector.component.js +2 -2
- package/esm2015/core/shared/components/order-state-label/order-state-label.component.js +2 -1
- package/esm2015/core/shared/components/product-search-input/product-search-input.component.js +1 -1
- package/esm2015/core/shared/components/product-selector/product-selector.component.js +1 -1
- package/esm2015/core/shared/components/radio-card/radio-card-fieldset.component.js +57 -0
- package/esm2015/core/shared/components/radio-card/radio-card.component.js +54 -0
- package/esm2015/core/shared/components/rich-text-editor/external-image-dialog/external-image-dialog.component.js +2 -2
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/context-menu/context-menu.component.js +140 -0
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/context-menu/context-menu.service.js +45 -0
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/custom-nodes.js +60 -0
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/menu/links.js +4 -4
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/menu/menu-common.js +23 -1
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/menu/menu-plugin.js +12 -0
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/menu/menu.js +73 -18
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/menu/sub-menu-with-icon.js +16 -0
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/plugins/image-plugin.js +100 -0
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/plugins/raw-editor-plugin.js +97 -0
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/plugins/tables-plugin.js +166 -0
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/prosemirror.service.js +47 -17
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/types.js +1 -1
- package/esm2015/core/shared/components/rich-text-editor/raw-html-dialog/raw-html-dialog.component.js +57 -0
- package/esm2015/core/shared/components/rich-text-editor/rich-text-editor.component.js +20 -9
- package/esm2015/core/shared/components/simple-dialog/simple-dialog.component.js +2 -2
- package/esm2015/core/shared/dynamic-form-inputs/code-editor-form-input/base-code-editor-form-input.component.js +59 -0
- package/esm2015/core/shared/dynamic-form-inputs/code-editor-form-input/html-editor-form-input.component.js +66 -0
- package/esm2015/core/shared/dynamic-form-inputs/code-editor-form-input/json-editor-form-input.component.js +47 -84
- package/esm2015/core/shared/dynamic-form-inputs/dynamic-form-input/dynamic-form-input.component.js +3 -3
- package/esm2015/core/shared/dynamic-form-inputs/register-dynamic-input-components.js +3 -1
- package/esm2015/core/shared/pipes/state-i18n-token.pipe.js +2 -1
- package/esm2015/core/shared/shared.module.js +13 -1
- package/esm2015/customer/components/customer-group-list/customer-group-list.component.js +2 -2
- package/esm2015/customer/components/customer-group-member-list/customer-group-member-list.component.js +6 -6
- package/esm2015/customer/components/customer-list/customer-list.component.js +2 -2
- package/esm2015/dashboard/dashboard.module.js +6 -2
- package/esm2015/order/components/coupon-code-selector/coupon-code-selector.component.js +42 -0
- package/esm2015/order/components/draft-order-detail/draft-order-detail.component.js +195 -0
- package/esm2015/order/components/draft-order-variant-selector/draft-order-variant-selector.component.js +59 -0
- package/esm2015/order/components/order-detail/order-detail.component.js +2 -2
- package/esm2015/order/components/order-editor/order-editor.component.js +5 -11
- package/esm2015/order/components/order-list/order-list.component.js +20 -4
- package/esm2015/order/components/order-table/order-table.component.js +16 -5
- package/esm2015/order/components/select-address-dialog/select-address-dialog.component.js +91 -0
- package/esm2015/order/components/select-address-dialog/select-address-dialog.graphql.js +14 -0
- package/esm2015/order/components/select-customer-dialog/select-customer-dialog.component.js +59 -0
- package/esm2015/order/components/select-shipping-method-dialog/select-shipping-method-dialog.component.js +30 -0
- package/esm2015/order/order.module.js +13 -1
- package/esm2015/order/order.routes.js +26 -7
- package/esm2015/order/providers/routing/order-resolver.js +29 -12
- package/esm2015/order/providers/routing/order.guard.js +41 -0
- package/esm2015/order/public_api.js +9 -1
- package/esm2015/settings/components/country-list/country-list.component.js +2 -2
- package/esm2015/settings/components/profile/profile.component.js +2 -2
- package/esm2015/settings/components/zone-list/zone-list.component.js +2 -2
- package/esm2015/settings/components/zone-member-list/zone-member-list.component.js +2 -2
- package/esm2015/system/components/health-check/health-check.component.js +1 -1
- package/fesm2015/vendure-admin-ui-catalog.js +835 -61
- package/fesm2015/vendure-admin-ui-catalog.js.map +1 -1
- package/fesm2015/vendure-admin-ui-core.js +3122 -1514
- package/fesm2015/vendure-admin-ui-core.js.map +1 -1
- package/fesm2015/vendure-admin-ui-customer.js +7 -7
- package/fesm2015/vendure-admin-ui-customer.js.map +1 -1
- package/fesm2015/vendure-admin-ui-dashboard.js +5 -1
- package/fesm2015/vendure-admin-ui-dashboard.js.map +1 -1
- package/fesm2015/vendure-admin-ui-order.js +780 -232
- package/fesm2015/vendure-admin-ui-order.js.map +1 -1
- package/fesm2015/vendure-admin-ui-settings.js +4 -4
- package/fesm2015/vendure-admin-ui-settings.js.map +1 -1
- package/fesm2015/vendure-admin-ui-system.js +1 -1
- package/order/components/coupon-code-selector/coupon-code-selector.component.d.ts +18 -0
- package/order/components/draft-order-detail/draft-order-detail.component.d.ts +49 -0
- package/order/components/draft-order-variant-selector/draft-order-variant-selector.component.d.ts +21 -0
- package/order/components/order-editor/order-editor.component.d.ts +1 -6
- package/order/components/order-list/order-list.component.d.ts +1 -0
- package/order/components/order-table/order-table.component.d.ts +11 -2
- package/order/components/select-address-dialog/select-address-dialog.component.d.ts +24 -0
- package/order/components/select-address-dialog/select-address-dialog.graphql.d.ts +1 -0
- package/order/components/select-customer-dialog/select-customer-dialog.component.d.ts +22 -0
- package/order/components/select-shipping-method-dialog/select-shipping-method-dialog.component.d.ts +16 -0
- package/order/providers/routing/order-resolver.d.ts +8 -5
- package/order/providers/routing/order.guard.d.ts +9 -0
- package/order/public_api.d.ts +8 -0
- package/order/vendure-admin-ui-order.metadata.json +1 -1
- package/package.json +13 -12
- package/settings/components/zone-member-list/zone-member-list.component.d.ts +3 -1
- package/settings/vendure-admin-ui-settings.metadata.json +1 -1
- package/static/i18n-messages/cs.json +33 -0
- package/static/i18n-messages/de.json +33 -0
- package/static/i18n-messages/en.json +36 -4
- package/static/i18n-messages/es.json +33 -0
- package/static/i18n-messages/fr.json +33 -0
- package/static/i18n-messages/it.json +33 -0
- package/static/i18n-messages/pl.json +33 -0
- package/static/i18n-messages/pt_BR.json +33 -0
- package/static/i18n-messages/pt_PT.json +33 -0
- package/static/i18n-messages/ru.json +33 -0
- package/static/i18n-messages/uk.json +33 -0
- package/static/i18n-messages/zh_Hans.json +33 -0
- package/static/i18n-messages/zh_Hant.json +33 -0
- package/static/styles/global/_forms.scss +4 -2
- package/static/styles/global/_overrides.scss +1 -1
- package/static/styles/global/_utilities.scss +4 -0
- package/static/theme.min.css +1 -1
- package/system/vendure-admin-ui-system.metadata.json +1 -1
- package/core/shared/components/rich-text-editor/prosemirror/menu/images.d.ts +0 -4
- package/esm2015/core/shared/components/rich-text-editor/prosemirror/menu/images.js +0 -36
|
@@ -3,9 +3,9 @@ import { Component, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, Injec
|
|
|
3
3
|
import * as i1 from '@angular/router';
|
|
4
4
|
import { Router, ActivatedRoute, RouterModule } from '@angular/router';
|
|
5
5
|
import * as i2 from '@vendure/admin-ui/core';
|
|
6
|
-
import { BaseDetailComponent, ServerConfigService, NotificationService, DataService, BaseListComponent, SortOrder, LogicalOperator, DeletionResult, ModalService, Permission, unicodePatternValidator, findTranslation, getConfigArgValue, createUpdatedTranslatable, encodeConfigArgValue, LocalStorageService, FacetValueSelectorComponent, flattenFacetValues, JobState, JobQueueService, getDefaultUiLanguage, BaseEntityResolver, AssetType, createResolveData, CanDeactivateDetailGuard, detailBreadcrumb, AssetPickerDialogComponent, AssetPreviewDialogComponent, GlobalFlag, SharedModule } from '@vendure/admin-ui/core';
|
|
6
|
+
import { BaseDetailComponent, ServerConfigService, NotificationService, DataService, BaseListComponent, SortOrder, LogicalOperator, DeletionResult, ModalService, Permission, unicodePatternValidator, findTranslation, getConfigArgValue, createUpdatedTranslatable, encodeConfigArgValue, LocalStorageService, SelectionManager, FacetValueSelectorComponent, flattenFacetValues, getChannelCodeFromUserStatus, JobState, JobQueueService, getDefaultUiLanguage, BaseEntityResolver, AssetType, createResolveData, CanDeactivateDetailGuard, detailBreadcrumb, AssetPickerDialogComponent, AssetPreviewDialogComponent, isMultiChannel, currentChannelIsNotDefault, GlobalFlag, SharedModule, BulkActionRegistryService } from '@vendure/admin-ui/core';
|
|
7
7
|
import { marker } from '@biesbjerg/ngx-translate-extract-marker';
|
|
8
|
-
import { map, debounceTime, takeUntil, finalize, switchMap, filter, take, mergeMap, shareReplay, distinctUntilChanged,
|
|
8
|
+
import { map, debounceTime, takeUntil, finalize, switchMap, filter, take, mergeMap, tap, shareReplay, distinctUntilChanged, mapTo, startWith, skipUntil, skip, withLatestFrom, delay, defaultIfEmpty, catchError } from 'rxjs/operators';
|
|
9
9
|
import { FormGroup, FormControl, FormBuilder, Validators, FormArray, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
10
10
|
import { BehaviorSubject, combineLatest, EMPTY, Subject, merge, of, forkJoin, throwError, from } from 'rxjs';
|
|
11
11
|
import { normalizeString } from '@vendure/common/lib/normalize-string';
|
|
@@ -17,6 +17,7 @@ import { unique } from '@vendure/common/lib/unique';
|
|
|
17
17
|
import { __awaiter } from 'tslib';
|
|
18
18
|
import { pick } from '@vendure/common/lib/pick';
|
|
19
19
|
import { moveItemInArray } from '@angular/cdk/drag-drop';
|
|
20
|
+
import { gql } from 'apollo-angular';
|
|
20
21
|
|
|
21
22
|
class AssetDetailComponent extends BaseDetailComponent {
|
|
22
23
|
constructor(router, route, serverConfigService, notificationService, dataService, formBuilder) {
|
|
@@ -415,9 +416,9 @@ class CollectionDetailComponent extends BaseDetailComponent {
|
|
|
415
416
|
CollectionDetailComponent.decorators = [
|
|
416
417
|
{ type: Component, args: [{
|
|
417
418
|
selector: 'vdr-collection-detail',
|
|
418
|
-
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
|
|
419
|
+
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<form class=\"form\" [formGroup]=\"detailForm\" *ngIf=\"entity$ | async as collection\">\r\n\r\n <nav role=\"navigation\">\r\n <ul class=\"collection-breadcrumbs\">\r\n <li *ngFor=\"let breadcrumb of collection.breadcrumbs; let isFirst = first; let isLast = last\">\r\n <a [routerLink]=\"['/catalog/collections']\" *ngIf=\"isFirst\">{{ 'catalog.root-collection' | translate }}</a>\r\n <a [routerLink]=\"['/catalog/collections', breadcrumb.id]\" *ngIf=\"!isFirst && !isLast\">{{ breadcrumb.name | translate }}</a>\r\n <ng-container *ngIf=\"isLast\">{{ breadcrumb.name | translate }}</ng-container>\r\n </li>\r\n </ul>\r\n </nav>\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\">{{\r\n 'catalog.public' | translate\r\n }}</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]=\"collection.assets\"\r\n [featuredAsset]=\"collection.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; trackBy:trackByFn\">\r\n <vdr-configurable-input\r\n (remove)=\"removeFilter(i)\"\r\n [position]=\"i\"\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\r\n [collectionId]=\"id\"\r\n [parentId]=\"parentId$ | async\"\r\n [updatedFilters]=\"updatedFilters$ | async\"\r\n [previewUpdatedFilters]=\"livePreview\"\r\n #collectionContents\r\n >\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 <clr-checkbox-wrapper [class.disabled]=\"detailForm.get('filters')?.pristine\">\r\n <input\r\n type=\"checkbox\"\r\n clrCheckbox\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n [disabled]=\"detailForm.get('filters')?.pristine\"\r\n [ngModel]=\"livePreview\"\r\n (ngModelChange)=\"toggleLivePreview()\"\r\n />\r\n <label>{{ 'catalog.live-preview-contents' | translate }}</label>\r\n </clr-checkbox-wrapper>\r\n </ng-template>\r\n </vdr-collection-contents>\r\n </div>\r\n </div>\r\n</form>\r\n",
|
|
419
420
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
420
|
-
styles: ["
|
|
421
|
+
styles: ["@charset \"UTF-8\";.visible-toggle{margin-top:-3px!important}clr-checkbox-wrapper{transition:opacity .3s}clr-checkbox-wrapper.disabled{opacity:.5}.collection-breadcrumbs{list-style-type:none;background-color:var(--color-component-bg-200);padding:2px 6px;margin-bottom:6px;border-radius:var(--clr-global-borderradius)}.collection-breadcrumbs li{font-size:.65rem;display:inline-block;margin-right:10px}.collection-breadcrumbs li:not(:last-child):after{content:\"\\203a\";top:0;color:var(--color-grey-400);margin-left:10px}\n"]
|
|
421
422
|
},] }
|
|
422
423
|
];
|
|
423
424
|
CollectionDetailComponent.ctorParameters = () => [
|
|
@@ -436,22 +437,30 @@ CollectionDetailComponent.propDecorators = {
|
|
|
436
437
|
};
|
|
437
438
|
|
|
438
439
|
class CollectionListComponent {
|
|
439
|
-
constructor(dataService, notificationService, modalService, router, route, serverConfigService) {
|
|
440
|
+
constructor(dataService, notificationService, modalService, router, route, serverConfigService, changeDetectorRef) {
|
|
440
441
|
this.dataService = dataService;
|
|
441
442
|
this.notificationService = notificationService;
|
|
442
443
|
this.modalService = modalService;
|
|
443
444
|
this.router = router;
|
|
444
445
|
this.route = route;
|
|
445
446
|
this.serverConfigService = serverConfigService;
|
|
447
|
+
this.changeDetectorRef = changeDetectorRef;
|
|
446
448
|
this.filterTermControl = new FormControl('');
|
|
447
449
|
this.expandAll = false;
|
|
448
450
|
this.expandedIds = [];
|
|
449
451
|
this.destroy$ = new Subject();
|
|
452
|
+
this.selectionManager = new SelectionManager({
|
|
453
|
+
additiveMode: true,
|
|
454
|
+
multiSelect: true,
|
|
455
|
+
itemsAreEqual: (a, b) => a.id === b.id,
|
|
456
|
+
});
|
|
450
457
|
}
|
|
451
458
|
ngOnInit() {
|
|
452
459
|
var _a, _b;
|
|
453
460
|
this.queryResult = this.dataService.collection.getCollections(1000, 0).refetchOnChannelChange();
|
|
454
|
-
this.items$ = this.queryResult
|
|
461
|
+
this.items$ = this.queryResult
|
|
462
|
+
.mapStream(data => data.collections.items)
|
|
463
|
+
.pipe(tap(items => this.selectionManager.setCurrentItems(items)), shareReplay(1));
|
|
455
464
|
this.activeCollectionId$ = this.route.paramMap.pipe(map(pm => pm.get('contents')), distinctUntilChanged());
|
|
456
465
|
this.expandedIds = (_b = (_a = this.route.snapshot.queryParamMap.get('expanded')) === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : [];
|
|
457
466
|
this.expandAll = this.route.snapshot.queryParamMap.get('expanded') === 'all';
|
|
@@ -559,9 +568,9 @@ class CollectionListComponent {
|
|
|
559
568
|
CollectionListComponent.decorators = [
|
|
560
569
|
{ type: Component, args: [{
|
|
561
570
|
selector: 'vdr-collection-list',
|
|
562
|
-
template: "<vdr-action-bar>\r\n <vdr-ab-left>\r\n <div class=\"
|
|
571
|
+
template: "<vdr-action-bar>\r\n <vdr-ab-left>\r\n <div class=\"\">\r\n <input\r\n type=\"text\"\r\n name=\"searchTerm\"\r\n [formControl]=\"filterTermControl\"\r\n [placeholder]=\"'catalog.filter-by-name' | translate\"\r\n class=\"clr-input search-input\"\r\n />\r\n <div class=\"flex center\">\r\n <clr-toggle-wrapper\r\n class=\"expand-all-toggle mt2\"\r\n >\r\n <input type=\"checkbox\" clrToggle [(ngModel)]=\"expandAll\" (change)=\"toggleExpandAll()\" />\r\n <label>\r\n {{ 'catalog.expand-all-collections' | translate }}\r\n </label>\r\n </clr-toggle-wrapper>\r\n <vdr-language-selector\r\n class=\"mt2\"\r\n [availableLanguageCodes]=\"availableLanguages$ | async\"\r\n [currentLanguageCode]=\"contentLanguage$ | async\"\r\n (languageCodeChange)=\"setLanguage($event)\"\r\n ></vdr-language-selector>\r\n </div>\r\n </div>\r\n </vdr-ab-left>\r\n <vdr-ab-right>\r\n <vdr-action-bar-items locationId=\"collection-list\"></vdr-action-bar-items>\r\n <a\r\n class=\"btn btn-primary\"\r\n *vdrIfPermissions=\"['CreateCatalog', 'CreateCollection']\"\r\n [routerLink]=\"['./create']\"\r\n >\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.create-new-collection' | translate }}\r\n </a>\r\n </vdr-ab-right>\r\n</vdr-action-bar>\r\n<div class=\"bulk-select-controls\">\r\n <input\r\n type=\"checkbox\"\r\n clrCheckbox\r\n [checked]=\"selectionManager.areAllCurrentItemsSelected()\"\r\n (click)=\"selectionManager.toggleSelectAll()\"\r\n />\r\n <vdr-bulk-action-menu\r\n class=\"ml2\"\r\n locationId=\"collection-list\"\r\n [hostComponent]=\"this\"\r\n [selectionManager]=\"selectionManager\"\r\n ></vdr-bulk-action-menu>\r\n</div>\r\n<div class=\"collection-wrapper\">\r\n <vdr-collection-tree\r\n [collections]=\"items$ | async\"\r\n [activeCollectionId]=\"activeCollectionId$ | async\"\r\n [expandAll]=\"expandAll\"\r\n [expandedIds]=\"expandedIds\"\r\n [selectionManager]=\"selectionManager\"\r\n (rearrange)=\"onRearrange($event)\"\r\n (deleteCollection)=\"deleteCollection($event)\"\r\n ></vdr-collection-tree>\r\n\r\n <div class=\"collection-contents\" [class.expanded]=\"activeCollectionId$ | async\">\r\n <vdr-collection-contents [collectionId]=\"activeCollectionId$ | async\">\r\n <ng-template let-count>\r\n <div class=\"collection-title\">\r\n {{ activeCollectionTitle$ | async }} ({{\r\n 'common.results-count' | translate: { count: count }\r\n }})\r\n </div>\r\n <button type=\"button\" class=\"close-button\" (click)=\"closeContents()\">\r\n <clr-icon shape=\"close\"></clr-icon>\r\n </button>\r\n </ng-template>\r\n </vdr-collection-contents>\r\n </div>\r\n</div>\r\n",
|
|
563
572
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
564
|
-
styles: [":host{height:100%;display:flex;flex-direction:column}.expand-all-toggle{display:block}.collection-wrapper{display:flex;height:calc(100% - 50px)}.collection-wrapper vdr-collection-tree{flex:1;height:100%;overflow:auto}.collection-wrapper .collection-contents{height:100%;width:0;opacity:0;visibility:hidden;overflow:auto;transition:width .3s,opacity .2s .3s,visibility 0s .3s}.collection-wrapper .collection-contents.expanded{width:30vw;visibility:visible;opacity:1;padding-left:12px}.collection-wrapper .collection-contents .close-button{margin:0;background:none;border:none;cursor:pointer}.paging-controls{padding-top:6px;border-top:1px solid var(--color-component-border-100);display:flex;justify-content:space-between}\n"]
|
|
573
|
+
styles: [":host{height:100%;display:flex;flex-direction:column}.bulk-select-controls{min-height:36px;padding-left:14px;display:flex;align-items:center;border-bottom:1px solid var(--color-component-border-200)}.expand-all-toggle{display:block}.collection-wrapper{display:flex;height:calc(100% - 50px)}.collection-wrapper vdr-collection-tree{flex:1;height:100%;overflow:auto}.collection-wrapper .collection-contents{height:100%;width:0;opacity:0;visibility:hidden;overflow:auto;transition:width .3s,opacity .2s .3s,visibility 0s .3s}.collection-wrapper .collection-contents.expanded{width:30vw;visibility:visible;opacity:1;padding-left:12px}.collection-wrapper .collection-contents .close-button{margin:0;background:none;border:none;cursor:pointer}.paging-controls{padding-top:6px;border-top:1px solid var(--color-component-border-100);display:flex;justify-content:space-between}\n"]
|
|
565
574
|
},] }
|
|
566
575
|
];
|
|
567
576
|
CollectionListComponent.ctorParameters = () => [
|
|
@@ -570,7 +579,8 @@ CollectionListComponent.ctorParameters = () => [
|
|
|
570
579
|
{ type: ModalService },
|
|
571
580
|
{ type: Router },
|
|
572
581
|
{ type: ActivatedRoute },
|
|
573
|
-
{ type: ServerConfigService }
|
|
582
|
+
{ type: ServerConfigService },
|
|
583
|
+
{ type: ChangeDetectorRef }
|
|
574
584
|
];
|
|
575
585
|
|
|
576
586
|
class FacetDetailComponent extends BaseDetailComponent {
|
|
@@ -914,6 +924,11 @@ class FacetListComponent extends BaseListComponent {
|
|
|
914
924
|
},
|
|
915
925
|
},
|
|
916
926
|
}));
|
|
927
|
+
this.selectionManager = new SelectionManager({
|
|
928
|
+
multiSelect: true,
|
|
929
|
+
itemsAreEqual: (a, b) => a.id === b.id,
|
|
930
|
+
additiveMode: true,
|
|
931
|
+
});
|
|
917
932
|
}
|
|
918
933
|
ngOnInit() {
|
|
919
934
|
super.ngOnInit();
|
|
@@ -967,7 +982,11 @@ class FacetListComponent extends BaseListComponent {
|
|
|
967
982
|
body: message,
|
|
968
983
|
buttons: [
|
|
969
984
|
{ type: 'secondary', label: marker('common.cancel') },
|
|
970
|
-
{
|
|
985
|
+
{
|
|
986
|
+
type: 'danger',
|
|
987
|
+
label: message ? marker('common.force-delete') : marker('common.delete'),
|
|
988
|
+
returnValue: true,
|
|
989
|
+
},
|
|
971
990
|
],
|
|
972
991
|
})
|
|
973
992
|
.pipe(switchMap(res => (res ? this.dataService.facet.deleteFacet(facetId, !!message) : EMPTY)), map(res => res.deleteFacet));
|
|
@@ -976,7 +995,7 @@ class FacetListComponent extends BaseListComponent {
|
|
|
976
995
|
FacetListComponent.decorators = [
|
|
977
996
|
{ type: Component, args: [{
|
|
978
997
|
selector: 'vdr-facet-list',
|
|
979
|
-
template: "<vdr-action-bar>\r\n <vdr-ab-left>\r\n <div class=\"
|
|
998
|
+
template: "<vdr-action-bar>\r\n <vdr-ab-left>\r\n <div class=\"\">\r\n <input\r\n type=\"text\"\r\n name=\"searchTerm\"\r\n [formControl]=\"filterTermControl\"\r\n [placeholder]=\"'catalog.filter-by-name' | translate\"\r\n class=\"clr-input search-input\"\r\n />\r\n <div>\r\n <vdr-language-selector\r\n [availableLanguageCodes]=\"availableLanguages$ | async\"\r\n [currentLanguageCode]=\"contentLanguage$ | async\"\r\n (languageCodeChange)=\"setLanguage($event)\"\r\n ></vdr-language-selector>\r\n </div>\r\n </div>\r\n </vdr-ab-left>\r\n <vdr-ab-right>\r\n <vdr-action-bar-items locationId=\"facet-list\"></vdr-action-bar-items>\r\n <a\r\n class=\"btn btn-primary\"\r\n *vdrIfPermissions=\"['CreateCatalog', 'CreateFacet']\"\r\n [routerLink]=\"['./create']\"\r\n >\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.create-new-facet' | translate }}\r\n </a>\r\n </vdr-ab-right>\r\n</vdr-action-bar>\r\n\r\n<vdr-data-table\r\n [items]=\"items$ | async\"\r\n [itemsPerPage]=\"itemsPerPage$ | async\"\r\n [totalItems]=\"totalItems$ | async\"\r\n [currentPage]=\"currentPage$ | async\"\r\n (pageChange)=\"setPageNumber($event)\"\r\n (itemsPerPageChange)=\"setItemsPerPage($event)\"\r\n [selectionManager]=\"selectionManager\"\r\n>\r\n <vdr-bulk-action-menu\r\n locationId=\"facet-list\"\r\n [hostComponent]=\"this\"\r\n [selectionManager]=\"selectionManager\"\r\n ></vdr-bulk-action-menu>\r\n <vdr-dt-column>{{ 'common.code' | translate }}</vdr-dt-column>\r\n <vdr-dt-column>{{ 'common.name' | translate }}</vdr-dt-column>\r\n <vdr-dt-column [expand]=\"true\">{{ 'catalog.values' | translate }}</vdr-dt-column>\r\n <vdr-dt-column>{{ 'catalog.visibility' | translate }}</vdr-dt-column>\r\n <vdr-dt-column></vdr-dt-column>\r\n <vdr-dt-column></vdr-dt-column>\r\n <ng-template let-facet=\"item\">\r\n <td class=\"left align-middle\" [class.private]=\"facet.isPrivate\">{{ facet.code }}</td>\r\n <td class=\"left align-middle\" [class.private]=\"facet.isPrivate\">{{ facet.name }}</td>\r\n <td class=\"left align-middle\" [class.private]=\"facet.isPrivate\">\r\n <vdr-facet-value-chip\r\n *ngFor=\"let value of facet.values | slice: 0:displayLimit[facet.id] || 3\"\r\n [facetValue]=\"value\"\r\n [removable]=\"false\"\r\n [displayFacetName]=\"false\"\r\n ></vdr-facet-value-chip>\r\n <button\r\n class=\"btn btn-sm btn-secondary btn-icon\"\r\n *ngIf=\"facet.values.length > initialLimit\"\r\n (click)=\"toggleDisplayLimit(facet)\"\r\n >\r\n <ng-container *ngIf=\"(displayLimit[facet.id] || 0) < facet.values.length; else collapse\">\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ facet.values.length - initialLimit }}\r\n </ng-container>\r\n <ng-template #collapse>\r\n <clr-icon shape=\"minus\"></clr-icon>\r\n </ng-template>\r\n </button>\r\n </td>\r\n <td class=\"left align-middle\" [class.private]=\"facet.isPrivate\">\r\n <vdr-chip>\r\n <ng-container *ngIf=\"!facet.isPrivate; else private\">{{\r\n 'catalog.public' | translate\r\n }}</ng-container>\r\n <ng-template #private>{{ 'catalog.private' | translate }}</ng-template>\r\n </vdr-chip>\r\n </td>\r\n <td class=\"right align-middle\" [class.private]=\"facet.isPrivate\">\r\n <vdr-table-row-action\r\n iconShape=\"edit\"\r\n [label]=\"'common.edit' | translate\"\r\n [linkTo]=\"['./', facet.id]\"\r\n ></vdr-table-row-action>\r\n </td>\r\n <td class=\"right align-middle\" [class.private]=\"facet.isPrivate\">\r\n <vdr-dropdown>\r\n <button type=\"button\" class=\"btn btn-link btn-sm\" vdrDropdownTrigger>\r\n {{ 'common.actions' | translate }}\r\n <clr-icon shape=\"caret down\"></clr-icon>\r\n </button>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n <button\r\n type=\"button\"\r\n class=\"delete-button\"\r\n (click)=\"deleteFacet(facet.id)\"\r\n [disabled]=\"!(['DeleteCatalog', 'DeleteFacet'] | hasPermission)\"\r\n vdrDropdownItem\r\n >\r\n <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon>\r\n {{ 'common.delete' | translate }}\r\n </button>\r\n </vdr-dropdown-menu>\r\n </vdr-dropdown>\r\n </td>\r\n </ng-template>\r\n</vdr-data-table>\r\n",
|
|
980
999
|
styles: ["td.private{background-color:var(--color-component-bg-200)}\n"]
|
|
981
1000
|
},] }
|
|
982
1001
|
];
|
|
@@ -1300,6 +1319,7 @@ class AssignProductsToChannelDialogComponent {
|
|
|
1300
1319
|
.subscribe(() => {
|
|
1301
1320
|
this.notificationService.success(marker('catalog.assign-product-to-channel-success'), {
|
|
1302
1321
|
channel: selectedChannel.code,
|
|
1322
|
+
count: this.productIds.length,
|
|
1303
1323
|
});
|
|
1304
1324
|
this.resolveWith(true);
|
|
1305
1325
|
});
|
|
@@ -1314,6 +1334,8 @@ class AssignProductsToChannelDialogComponent {
|
|
|
1314
1334
|
.subscribe(() => {
|
|
1315
1335
|
this.notificationService.success(marker('catalog.assign-variant-to-channel-success'), {
|
|
1316
1336
|
channel: selectedChannel.code,
|
|
1337
|
+
// tslint:disable-next-line:no-non-null-assertion
|
|
1338
|
+
count: this.productVariantIds.length,
|
|
1317
1339
|
});
|
|
1318
1340
|
this.resolveWith(true);
|
|
1319
1341
|
});
|
|
@@ -1480,15 +1502,21 @@ class ProductDetailComponent extends BaseDetailComponent {
|
|
|
1480
1502
|
.subscribe();
|
|
1481
1503
|
}
|
|
1482
1504
|
removeFromChannel(channelId) {
|
|
1483
|
-
this.
|
|
1484
|
-
.
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1505
|
+
from(getChannelCodeFromUserStatus(this.dataService, channelId))
|
|
1506
|
+
.pipe(switchMap(({ channelCode }) => {
|
|
1507
|
+
return this.modalService.dialog({
|
|
1508
|
+
title: marker('catalog.remove-product-from-channel'),
|
|
1509
|
+
buttons: [
|
|
1510
|
+
{ type: 'secondary', label: marker('common.cancel') },
|
|
1511
|
+
{
|
|
1512
|
+
type: 'danger',
|
|
1513
|
+
label: marker('catalog.remove-from-channel'),
|
|
1514
|
+
translationVars: { channelCode },
|
|
1515
|
+
returnValue: true,
|
|
1516
|
+
},
|
|
1517
|
+
],
|
|
1518
|
+
});
|
|
1519
|
+
}), switchMap(response => response
|
|
1492
1520
|
? this.dataService.product.removeProductsFromChannel({
|
|
1493
1521
|
channelId,
|
|
1494
1522
|
productIds: [this.id],
|
|
@@ -1513,15 +1541,21 @@ class ProductDetailComponent extends BaseDetailComponent {
|
|
|
1513
1541
|
.subscribe();
|
|
1514
1542
|
}
|
|
1515
1543
|
removeVariantFromChannel({ channelId, variant, }) {
|
|
1516
|
-
this.
|
|
1517
|
-
.
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1544
|
+
from(getChannelCodeFromUserStatus(this.dataService, channelId))
|
|
1545
|
+
.pipe(switchMap(({ channelCode }) => {
|
|
1546
|
+
return this.modalService.dialog({
|
|
1547
|
+
title: marker('catalog.remove-product-variant-from-channel'),
|
|
1548
|
+
buttons: [
|
|
1549
|
+
{ type: 'secondary', label: marker('common.cancel') },
|
|
1550
|
+
{
|
|
1551
|
+
type: 'danger',
|
|
1552
|
+
label: marker('catalog.remove-from-channel'),
|
|
1553
|
+
translationVars: { channelCode },
|
|
1554
|
+
returnValue: true,
|
|
1555
|
+
},
|
|
1556
|
+
],
|
|
1557
|
+
});
|
|
1558
|
+
}), switchMap(response => response
|
|
1525
1559
|
? this.dataService.product.removeVariantsFromChannel({
|
|
1526
1560
|
channelId,
|
|
1527
1561
|
productVariantIds: [variant.id],
|
|
@@ -1835,9 +1869,9 @@ class ProductDetailComponent extends BaseDetailComponent {
|
|
|
1835
1869
|
ProductDetailComponent.decorators = [
|
|
1836
1870
|
{ type: Component, args: [{
|
|
1837
1871
|
selector: 'vdr-product-detail',
|
|
1838
|
-
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",
|
|
1872
|
+
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 <span class=\"full-label\">{{ 'catalog.display-variant-cards' | translate }}</span>\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 <span class=\"full-label\">{{ 'catalog.display-variant-table' | translate }}</span>\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 mb0 mr0\"\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",
|
|
1839
1873
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1840
|
-
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:
|
|
1874
|
+
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;flex-direction:column;justify-content:space-between}@media screen and (min-width: 768px){.view-mode{flex-direction:row}}.edit-variants-btn{margin-top:0}.channel-assignment{flex-wrap:wrap;max-height:144px;overflow-y:auto}.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"]
|
|
1841
1875
|
},] }
|
|
1842
1876
|
];
|
|
1843
1877
|
ProductDetailComponent.ctorParameters = () => [
|
|
@@ -1892,6 +1926,11 @@ class ProductListComponent extends BaseListComponent {
|
|
|
1892
1926
|
groupByProduct: this.groupByProduct,
|
|
1893
1927
|
},
|
|
1894
1928
|
}));
|
|
1929
|
+
this.selectionManager = new SelectionManager({
|
|
1930
|
+
multiSelect: true,
|
|
1931
|
+
itemsAreEqual: (a, b) => this.groupByProduct ? a.productId === b.productId : a.productVariantId === b.productVariantId,
|
|
1932
|
+
additiveMode: true,
|
|
1933
|
+
});
|
|
1895
1934
|
}
|
|
1896
1935
|
ngOnInit() {
|
|
1897
1936
|
super.ngOnInit();
|
|
@@ -1983,8 +2022,8 @@ class ProductListComponent extends BaseListComponent {
|
|
|
1983
2022
|
ProductListComponent.decorators = [
|
|
1984
2023
|
{ type: Component, args: [{
|
|
1985
2024
|
selector: 'vdr-products-list',
|
|
1986
|
-
template: "<vdr-action-bar>\r\n <vdr-ab-left [grow]=\"true\">\r\n <div class=\"search-form\">\r\n <vdr-product-search-input\r\n #productSearchInputComponent\r\n [facetValueResults]=\"facetValues$ | async\"\r\n (searchTermChange)=\"setSearchTerm($event)\"\r\n (facetValueChange)=\"setFacetValueIds($event)\"\r\n ></vdr-product-search-input>\r\n <vdr-dropdown class=\"search-settings-menu mr3\">\r\n <button\r\n type=\"button\"\r\n class=\"icon-button search-index-button\"\r\n [title]=\"\r\n (pendingSearchIndexUpdates\r\n ? 'catalog.pending-search-index-updates'\r\n : 'catalog.search-index-controls'\r\n ) | translate\r\n \"\r\n vdrDropdownTrigger\r\n >\r\n <clr-icon shape=\"cog\"></clr-icon>\r\n <vdr-status-badge *ngIf=\"pendingSearchIndexUpdates\" type=\"warning\"></vdr-status-badge>\r\n </button>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n <h4 class=\"dropdown-header\">{{ 'catalog.search-index-controls' | translate }}</h4>\r\n <ng-container *ngIf=\"pendingSearchIndexUpdates\">\r\n <button\r\n type=\"button\"\r\n class=\"run-updates-button\"\r\n vdrDropdownItem\r\n (click)=\"runPendingSearchIndexUpdates()\"\r\n [disabled]=\"!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)\"\r\n >\r\n <vdr-status-badge type=\"warning\"></vdr-status-badge>\r\n {{\r\n
|
|
1987
|
-
styles: [".image-col{width:70px}.image-placeholder{width:50px;height:50px;background-color:var(--color-component-bg-200)}.image-placeholder img{border-radius:var(--border-radius-img)}.image-placeholder .placeholder{text-align:center;color:var(--color-grey-300)}.search-form{display:flex;align-items:center;width:100
|
|
2025
|
+
template: "<vdr-action-bar>\r\n <vdr-ab-left [grow]=\"true\">\r\n <div class=\"search-form\">\r\n <vdr-product-search-input\r\n #productSearchInputComponent\r\n [facetValueResults]=\"facetValues$ | async\"\r\n (searchTermChange)=\"setSearchTerm($event)\"\r\n (facetValueChange)=\"setFacetValueIds($event)\"\r\n ></vdr-product-search-input>\r\n <vdr-dropdown class=\"search-settings-menu mr3\">\r\n <button\r\n type=\"button\"\r\n class=\"icon-button search-index-button\"\r\n [title]=\"\r\n (pendingSearchIndexUpdates\r\n ? 'catalog.pending-search-index-updates'\r\n : 'catalog.search-index-controls'\r\n ) | translate\r\n \"\r\n vdrDropdownTrigger\r\n >\r\n <clr-icon shape=\"cog\"></clr-icon>\r\n <vdr-status-badge *ngIf=\"pendingSearchIndexUpdates\" type=\"warning\"></vdr-status-badge>\r\n </button>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n <h4 class=\"dropdown-header\">{{ 'catalog.search-index-controls' | translate }}</h4>\r\n <ng-container *ngIf=\"pendingSearchIndexUpdates\">\r\n <button\r\n type=\"button\"\r\n class=\"run-updates-button\"\r\n vdrDropdownItem\r\n (click)=\"runPendingSearchIndexUpdates()\"\r\n [disabled]=\"!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)\"\r\n >\r\n <vdr-status-badge type=\"warning\"></vdr-status-badge>\r\n {{\r\n 'catalog.run-pending-search-index-updates'\r\n | translate: { count: pendingSearchIndexUpdates }\r\n }}\r\n </button>\r\n <div class=\"dropdown-divider\"></div>\r\n </ng-container>\r\n <button\r\n type=\"button\"\r\n vdrDropdownItem\r\n (click)=\"rebuildSearchIndex()\"\r\n [disabled]=\"!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)\"\r\n >\r\n {{ 'catalog.rebuild-search-index' | translate }}\r\n </button>\r\n </vdr-dropdown-menu>\r\n </vdr-dropdown>\r\n </div>\r\n <div class=\"flex wrap\">\r\n <clr-toggle-wrapper class=\"mt2\">\r\n <input type=\"checkbox\" clrToggle [(ngModel)]=\"groupByProduct\" (ngModelChange)=\"refresh()\" />\r\n <label>\r\n {{ 'catalog.group-by-product' | translate }}\r\n </label>\r\n </clr-toggle-wrapper>\r\n <vdr-language-selector\r\n [availableLanguageCodes]=\"availableLanguages$ | async\"\r\n [currentLanguageCode]=\"contentLanguage$ | async\"\r\n (languageCodeChange)=\"setLanguage($event)\"\r\n ></vdr-language-selector>\r\n </div>\r\n </vdr-ab-left>\r\n <vdr-ab-right>\r\n <vdr-action-bar-items locationId=\"product-list\"></vdr-action-bar-items>\r\n <a\r\n class=\"btn btn-primary\"\r\n [routerLink]=\"['./create']\"\r\n *vdrIfPermissions=\"['CreateCatalog', 'CreateProduct']\"\r\n >\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.create-new-product' | translate }}\r\n </a>\r\n </vdr-ab-right>\r\n</vdr-action-bar>\r\n\r\n<vdr-data-table\r\n [items]=\"items$ | async\"\r\n [itemsPerPage]=\"itemsPerPage$ | async\"\r\n [totalItems]=\"totalItems$ | async\"\r\n [currentPage]=\"currentPage$ | async\"\r\n (pageChange)=\"setPageNumber($event)\"\r\n (itemsPerPageChange)=\"setItemsPerPage($event)\"\r\n [selectionManager]=\"selectionManager\"\r\n>\r\n <vdr-bulk-action-menu\r\n locationId=\"product-list\"\r\n [hostComponent]=\"this\"\r\n [selectionManager]=\"selectionManager\"\r\n ></vdr-bulk-action-menu>\r\n <vdr-dt-column> </vdr-dt-column>\r\n <vdr-dt-column></vdr-dt-column>\r\n <vdr-dt-column></vdr-dt-column>\r\n <vdr-dt-column></vdr-dt-column>\r\n <ng-template let-result=\"item\">\r\n <td class=\"left align-middle image-col\" [class.disabled]=\"!result.enabled\">\r\n <div class=\"image-placeholder\">\r\n <img\r\n *ngIf=\"\r\n groupByProduct\r\n ? result.productAsset\r\n : result.productVariantAsset || result.productAsset as asset;\r\n else imagePlaceholder\r\n \"\r\n [src]=\"asset | assetPreview: 'tiny'\"\r\n />\r\n <ng-template #imagePlaceholder>\r\n <div class=\"placeholder\">\r\n <clr-icon shape=\"image\" size=\"48\"></clr-icon>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </td>\r\n <td class=\"left align-middle\" [class.disabled]=\"!result.enabled\">\r\n <div>{{ groupByProduct ? result.productName : result.productVariantName }}</div>\r\n <div *ngIf=\"!groupByProduct\" class=\"sku\">{{ result.sku }}</div>\r\n </td>\r\n <td class=\"align-middle\" [class.disabled]=\"!result.enabled\">\r\n <vdr-chip *ngIf=\"!result.enabled\">{{ 'common.disabled' | translate }}</vdr-chip>\r\n </td>\r\n <td class=\"right align-middle\" [class.disabled]=\"!result.enabled\">\r\n <vdr-table-row-action\r\n class=\"edit-button\"\r\n iconShape=\"edit\"\r\n [label]=\"'common.edit' | translate\"\r\n [linkTo]=\"['./', result.productId]\"\r\n ></vdr-table-row-action>\r\n <vdr-dropdown>\r\n <button type=\"button\" class=\"btn btn-link btn-sm\" vdrDropdownTrigger>\r\n {{ 'common.actions' | translate }}\r\n <clr-icon shape=\"caret down\"></clr-icon>\r\n </button>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n <button\r\n type=\"button\"\r\n class=\"delete-button\"\r\n (click)=\"deleteProduct(result.productId)\"\r\n [disabled]=\"!(['DeleteCatalog', 'DeleteProduct'] | hasPermission)\"\r\n vdrDropdownItem\r\n >\r\n <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon>\r\n {{ 'common.delete' | translate }}\r\n </button>\r\n </vdr-dropdown-menu>\r\n </vdr-dropdown>\r\n </td>\r\n </ng-template>\r\n</vdr-data-table>\r\n",
|
|
2026
|
+
styles: [".image-col{width:70px}.image-placeholder{width:50px;height:50px;background-color:var(--color-component-bg-200)}.image-placeholder img{border-radius:var(--border-radius-img)}.image-placeholder .placeholder{text-align:center;color:var(--color-grey-300)}.search-form{display:flex;align-items:center;width:100%}vdr-product-search-input{min-width:300px}@media screen and (max-width: 768px){vdr-product-search-input{min-width:100px}}.search-settings-menu{margin:0 12px}td.disabled{background-color:var(--color-component-bg-200)}.search-index-button{position:relative}.search-index-button vdr-status-badge{right:0;top:0}.run-updates-button{position:relative}.run-updates-button vdr-status-badge{left:10px;top:10px}.edit-button{margin-right:24px}.sku{color:var(--color-text-300)}\n"]
|
|
1988
2027
|
},] }
|
|
1989
2028
|
];
|
|
1990
2029
|
ProductListComponent.ctorParameters = () => [
|
|
@@ -2627,6 +2666,7 @@ class CollectionResolver extends BaseEntityResolver {
|
|
|
2627
2666
|
name: '',
|
|
2628
2667
|
slug: '',
|
|
2629
2668
|
isPrivate: false,
|
|
2669
|
+
breadcrumbs: [],
|
|
2630
2670
|
description: '',
|
|
2631
2671
|
featuredAsset: null,
|
|
2632
2672
|
assets: [],
|
|
@@ -2735,88 +2775,88 @@ ProductVariantsResolver.ctorParameters = () => [
|
|
|
2735
2775
|
{ type: DataService }
|
|
2736
2776
|
];
|
|
2737
2777
|
|
|
2738
|
-
const ɵ0 = {
|
|
2778
|
+
const ɵ0$3 = {
|
|
2739
2779
|
breadcrumb: marker('breadcrumb.products'),
|
|
2740
|
-
}, ɵ1 = {
|
|
2780
|
+
}, ɵ1$3 = {
|
|
2741
2781
|
breadcrumb: productBreadcrumb,
|
|
2742
|
-
}, ɵ2 = {
|
|
2782
|
+
}, ɵ2$3 = {
|
|
2743
2783
|
breadcrumb: productVariantEditorBreadcrumb,
|
|
2744
|
-
}, ɵ3 = {
|
|
2784
|
+
}, ɵ3$3 = {
|
|
2745
2785
|
breadcrumb: productOptionsEditorBreadcrumb,
|
|
2746
|
-
}, ɵ4 = {
|
|
2786
|
+
}, ɵ4$3 = {
|
|
2747
2787
|
breadcrumb: marker('breadcrumb.facets'),
|
|
2748
|
-
}, ɵ5 = {
|
|
2788
|
+
}, ɵ5$3 = {
|
|
2749
2789
|
breadcrumb: facetBreadcrumb,
|
|
2750
|
-
}, ɵ6 = {
|
|
2790
|
+
}, ɵ6$3 = {
|
|
2751
2791
|
breadcrumb: marker('breadcrumb.collections'),
|
|
2752
|
-
}, ɵ7 = {
|
|
2792
|
+
}, ɵ7$3 = {
|
|
2753
2793
|
breadcrumb: collectionBreadcrumb,
|
|
2754
|
-
}, ɵ8 = {
|
|
2794
|
+
}, ɵ8$3 = {
|
|
2755
2795
|
breadcrumb: marker('breadcrumb.assets'),
|
|
2756
|
-
}, ɵ9 = {
|
|
2796
|
+
}, ɵ9$1 = {
|
|
2757
2797
|
breadcrumb: assetBreadcrumb,
|
|
2758
2798
|
};
|
|
2759
2799
|
const catalogRoutes = [
|
|
2760
2800
|
{
|
|
2761
2801
|
path: 'products',
|
|
2762
2802
|
component: ProductListComponent,
|
|
2763
|
-
data: ɵ0,
|
|
2803
|
+
data: ɵ0$3,
|
|
2764
2804
|
},
|
|
2765
2805
|
{
|
|
2766
2806
|
path: 'products/:id',
|
|
2767
2807
|
component: ProductDetailComponent,
|
|
2768
2808
|
resolve: createResolveData(ProductResolver),
|
|
2769
2809
|
canDeactivate: [CanDeactivateDetailGuard],
|
|
2770
|
-
data: ɵ1,
|
|
2810
|
+
data: ɵ1$3,
|
|
2771
2811
|
},
|
|
2772
2812
|
{
|
|
2773
2813
|
path: 'products/:id/manage-variants',
|
|
2774
2814
|
component: ProductVariantsEditorComponent,
|
|
2775
2815
|
resolve: createResolveData(ProductVariantsResolver),
|
|
2776
2816
|
canDeactivate: [CanDeactivateDetailGuard],
|
|
2777
|
-
data: ɵ2,
|
|
2817
|
+
data: ɵ2$3,
|
|
2778
2818
|
},
|
|
2779
2819
|
{
|
|
2780
2820
|
path: 'products/:id/options',
|
|
2781
2821
|
component: ProductOptionsEditorComponent,
|
|
2782
2822
|
resolve: createResolveData(ProductVariantsResolver),
|
|
2783
2823
|
canDeactivate: [CanDeactivateDetailGuard],
|
|
2784
|
-
data: ɵ3,
|
|
2824
|
+
data: ɵ3$3,
|
|
2785
2825
|
},
|
|
2786
2826
|
{
|
|
2787
2827
|
path: 'facets',
|
|
2788
2828
|
component: FacetListComponent,
|
|
2789
|
-
data: ɵ4,
|
|
2829
|
+
data: ɵ4$3,
|
|
2790
2830
|
},
|
|
2791
2831
|
{
|
|
2792
2832
|
path: 'facets/:id',
|
|
2793
2833
|
component: FacetDetailComponent,
|
|
2794
2834
|
resolve: createResolveData(FacetResolver),
|
|
2795
2835
|
canDeactivate: [CanDeactivateDetailGuard],
|
|
2796
|
-
data: ɵ5,
|
|
2836
|
+
data: ɵ5$3,
|
|
2797
2837
|
},
|
|
2798
2838
|
{
|
|
2799
2839
|
path: 'collections',
|
|
2800
2840
|
component: CollectionListComponent,
|
|
2801
|
-
data: ɵ6,
|
|
2841
|
+
data: ɵ6$3,
|
|
2802
2842
|
},
|
|
2803
2843
|
{
|
|
2804
2844
|
path: 'collections/:id',
|
|
2805
2845
|
component: CollectionDetailComponent,
|
|
2806
2846
|
resolve: createResolveData(CollectionResolver),
|
|
2807
2847
|
canDeactivate: [CanDeactivateDetailGuard],
|
|
2808
|
-
data: ɵ7,
|
|
2848
|
+
data: ɵ7$3,
|
|
2809
2849
|
},
|
|
2810
2850
|
{
|
|
2811
2851
|
path: 'assets',
|
|
2812
2852
|
component: AssetListComponent,
|
|
2813
|
-
data: ɵ8,
|
|
2853
|
+
data: ɵ8$3,
|
|
2814
2854
|
},
|
|
2815
2855
|
{
|
|
2816
2856
|
path: 'assets/:id',
|
|
2817
2857
|
component: AssetDetailComponent,
|
|
2818
2858
|
resolve: createResolveData(AssetResolver),
|
|
2819
|
-
data: ɵ9,
|
|
2859
|
+
data: ɵ9$1,
|
|
2820
2860
|
},
|
|
2821
2861
|
];
|
|
2822
2862
|
function productBreadcrumb(data, params) {
|
|
@@ -2981,6 +3021,206 @@ AssetsComponent.propDecorators = {
|
|
|
2981
3021
|
updatePermissions: [{ type: Input }]
|
|
2982
3022
|
};
|
|
2983
3023
|
|
|
3024
|
+
class AssignToChannelDialogComponent {
|
|
3025
|
+
// assigned by ModalService.fromComponent() call
|
|
3026
|
+
constructor(dataService, notificationService) {
|
|
3027
|
+
this.dataService = dataService;
|
|
3028
|
+
this.notificationService = notificationService;
|
|
3029
|
+
this.selectedChannelIdControl = new FormControl();
|
|
3030
|
+
}
|
|
3031
|
+
ngOnInit() {
|
|
3032
|
+
const activeChannelId$ = this.dataService.client
|
|
3033
|
+
.userStatus()
|
|
3034
|
+
.mapSingle(({ userStatus }) => userStatus.activeChannelId);
|
|
3035
|
+
const allChannels$ = this.dataService.settings.getChannels().mapSingle(data => data.channels);
|
|
3036
|
+
combineLatest(activeChannelId$, allChannels$).subscribe(([activeChannelId, channels]) => {
|
|
3037
|
+
// tslint:disable-next-line:no-non-null-assertion
|
|
3038
|
+
this.currentChannel = channels.find(c => c.id === activeChannelId);
|
|
3039
|
+
this.availableChannels = channels;
|
|
3040
|
+
});
|
|
3041
|
+
this.selectedChannelIdControl.valueChanges.subscribe(ids => {
|
|
3042
|
+
this.selectChannel(ids);
|
|
3043
|
+
});
|
|
3044
|
+
}
|
|
3045
|
+
selectChannel(channelIds) {
|
|
3046
|
+
this.selectedChannel = this.availableChannels.find(c => c.id === channelIds[0]);
|
|
3047
|
+
}
|
|
3048
|
+
assign() {
|
|
3049
|
+
const selectedChannel = this.selectedChannel;
|
|
3050
|
+
if (selectedChannel) {
|
|
3051
|
+
this.resolveWith(selectedChannel);
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
cancel() {
|
|
3055
|
+
this.resolveWith();
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
AssignToChannelDialogComponent.decorators = [
|
|
3059
|
+
{ type: Component, args: [{
|
|
3060
|
+
selector: 'vdr-assign-to-channel-dialog',
|
|
3061
|
+
template: "<ng-template vdrDialogTitle>\r\n {{ 'catalog.assign-to-channel' | translate }}\r\n</ng-template>\r\n<clr-input-container class=\"mb4\">\r\n <label>{{ 'common.channel' | translate }}</label>\r\n <vdr-channel-assignment-control\r\n clrInput\r\n [multiple]=\"false\"\r\n [includeDefaultChannel]=\"false\"\r\n [formControl]=\"selectedChannelIdControl\"\r\n ></vdr-channel-assignment-control>\r\n</clr-input-container>\r\n\r\n<ng-template vdrDialogButtons>\r\n <button type=\"button\" class=\"btn\" (click)=\"cancel()\">{{ 'common.cancel' | translate }}</button>\r\n <button type=\"submit\" (click)=\"assign()\" [disabled]=\"!selectedChannel\" class=\"btn btn-primary\">\r\n <ng-template [ngIf]=\"selectedChannel\" [ngIfElse]=\"noSelection\">\r\n {{ 'catalog.assign-to-named-channel' | translate: { channelCode: selectedChannel?.code } }}\r\n </ng-template>\r\n <ng-template #noSelection>\r\n {{ 'catalog.no-channel-selected' | translate }}\r\n </ng-template>\r\n </button>\r\n</ng-template>\r\n",
|
|
3062
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3063
|
+
styles: ["vdr-channel-assignment-control{min-width:200px}\n"]
|
|
3064
|
+
},] }
|
|
3065
|
+
];
|
|
3066
|
+
AssignToChannelDialogComponent.ctorParameters = () => [
|
|
3067
|
+
{ type: DataService },
|
|
3068
|
+
{ type: NotificationService }
|
|
3069
|
+
];
|
|
3070
|
+
|
|
3071
|
+
const GET_PRODUCTS_WITH_FACET_VALUES_BY_IDS = gql `
|
|
3072
|
+
query GetProductsWithFacetValuesByIds($ids: [String!]!) {
|
|
3073
|
+
products(options: { filter: { id: { in: $ids } } }) {
|
|
3074
|
+
items {
|
|
3075
|
+
id
|
|
3076
|
+
name
|
|
3077
|
+
facetValues {
|
|
3078
|
+
id
|
|
3079
|
+
name
|
|
3080
|
+
code
|
|
3081
|
+
facet {
|
|
3082
|
+
id
|
|
3083
|
+
name
|
|
3084
|
+
code
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
3090
|
+
`;
|
|
3091
|
+
const GET_VARIANTS_WITH_FACET_VALUES_BY_IDS = gql `
|
|
3092
|
+
query GetVariantsWithFacetValuesByIds($ids: [String!]!) {
|
|
3093
|
+
productVariants(options: { filter: { id: { in: $ids } } }) {
|
|
3094
|
+
items {
|
|
3095
|
+
id
|
|
3096
|
+
name
|
|
3097
|
+
sku
|
|
3098
|
+
facetValues {
|
|
3099
|
+
id
|
|
3100
|
+
name
|
|
3101
|
+
code
|
|
3102
|
+
facet {
|
|
3103
|
+
id
|
|
3104
|
+
name
|
|
3105
|
+
code
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
`;
|
|
3112
|
+
const UPDATE_PRODUCTS_BULK = gql `
|
|
3113
|
+
mutation UpdateProductsBulk($input: [UpdateProductInput!]!) {
|
|
3114
|
+
updateProducts(input: $input) {
|
|
3115
|
+
id
|
|
3116
|
+
name
|
|
3117
|
+
facetValues {
|
|
3118
|
+
id
|
|
3119
|
+
name
|
|
3120
|
+
code
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
`;
|
|
3125
|
+
const UPDATE_VARIANTS_BULK = gql `
|
|
3126
|
+
mutation UpdateVariantsBulk($input: [UpdateProductVariantInput!]!) {
|
|
3127
|
+
updateProductVariants(input: $input) {
|
|
3128
|
+
id
|
|
3129
|
+
name
|
|
3130
|
+
facetValues {
|
|
3131
|
+
id
|
|
3132
|
+
name
|
|
3133
|
+
code
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
`;
|
|
3138
|
+
|
|
3139
|
+
class BulkAddFacetValuesDialogComponent {
|
|
3140
|
+
constructor(dataService, changeDetectorRef) {
|
|
3141
|
+
this.dataService = dataService;
|
|
3142
|
+
this.changeDetectorRef = changeDetectorRef;
|
|
3143
|
+
/* provided by call to ModalService */
|
|
3144
|
+
this.mode = 'product';
|
|
3145
|
+
this.facets = [];
|
|
3146
|
+
this.state = 'loading';
|
|
3147
|
+
this.selectedValues = [];
|
|
3148
|
+
this.items = [];
|
|
3149
|
+
this.facetValuesRemoved = false;
|
|
3150
|
+
}
|
|
3151
|
+
ngOnInit() {
|
|
3152
|
+
var _a, _b;
|
|
3153
|
+
const fetchData$ = this.mode === 'product'
|
|
3154
|
+
? this.dataService
|
|
3155
|
+
.query(GET_PRODUCTS_WITH_FACET_VALUES_BY_IDS, {
|
|
3156
|
+
ids: (_a = this.ids) !== null && _a !== void 0 ? _a : [],
|
|
3157
|
+
})
|
|
3158
|
+
.mapSingle(({ products }) => products.items.map(p => (Object.assign(Object.assign({}, p), { facetValues: [...p.facetValues] }))))
|
|
3159
|
+
: this.dataService
|
|
3160
|
+
.query(GET_VARIANTS_WITH_FACET_VALUES_BY_IDS, {
|
|
3161
|
+
ids: (_b = this.ids) !== null && _b !== void 0 ? _b : [],
|
|
3162
|
+
})
|
|
3163
|
+
.mapSingle(({ productVariants }) => productVariants.items.map(p => (Object.assign(Object.assign({}, p), { facetValues: [...p.facetValues] }))));
|
|
3164
|
+
this.subscription = fetchData$.subscribe({
|
|
3165
|
+
next: items => {
|
|
3166
|
+
this.items = items;
|
|
3167
|
+
this.state = 'ready';
|
|
3168
|
+
this.changeDetectorRef.markForCheck();
|
|
3169
|
+
},
|
|
3170
|
+
});
|
|
3171
|
+
}
|
|
3172
|
+
ngOnDestroy() {
|
|
3173
|
+
var _a;
|
|
3174
|
+
(_a = this.subscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
3175
|
+
}
|
|
3176
|
+
cancel() {
|
|
3177
|
+
this.resolveWith();
|
|
3178
|
+
}
|
|
3179
|
+
removeFacetValue(item, facetValueId) {
|
|
3180
|
+
item.facetValues = item.facetValues.filter(fv => fv.id !== facetValueId);
|
|
3181
|
+
this.facetValuesRemoved = true;
|
|
3182
|
+
}
|
|
3183
|
+
addFacetValues() {
|
|
3184
|
+
var _a, _b;
|
|
3185
|
+
const selectedFacetValueIds = this.selectedValues.map(sv => sv.id);
|
|
3186
|
+
this.state = 'saving';
|
|
3187
|
+
const save$ = this.mode === 'product'
|
|
3188
|
+
? this.dataService.mutate(UPDATE_PRODUCTS_BULK, {
|
|
3189
|
+
input: (_a = this.items) === null || _a === void 0 ? void 0 : _a.map(product => ({
|
|
3190
|
+
id: product.id,
|
|
3191
|
+
facetValueIds: unique([
|
|
3192
|
+
...product.facetValues.map(fv => fv.id),
|
|
3193
|
+
...selectedFacetValueIds,
|
|
3194
|
+
]),
|
|
3195
|
+
})),
|
|
3196
|
+
})
|
|
3197
|
+
: this.dataService.mutate(UPDATE_VARIANTS_BULK, {
|
|
3198
|
+
input: (_b = this.items) === null || _b === void 0 ? void 0 : _b.map(product => ({
|
|
3199
|
+
id: product.id,
|
|
3200
|
+
facetValueIds: unique([
|
|
3201
|
+
...product.facetValues.map(fv => fv.id),
|
|
3202
|
+
...selectedFacetValueIds,
|
|
3203
|
+
]),
|
|
3204
|
+
})),
|
|
3205
|
+
});
|
|
3206
|
+
return save$.subscribe(result => {
|
|
3207
|
+
this.resolveWith(this.selectedValues);
|
|
3208
|
+
});
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
BulkAddFacetValuesDialogComponent.decorators = [
|
|
3212
|
+
{ type: Component, args: [{
|
|
3213
|
+
selector: 'vdr-bulk-add-facet-values-dialog',
|
|
3214
|
+
template: "<ng-template vdrDialogTitle>\r\n {{ 'catalog.edit-facet-values' | translate }}\r\n</ng-template>\r\n\r\n<div class=\"flex\">\r\n <div class=\"flex center\">\r\n <div class=\"mr2\">\r\n {{ 'catalog.add-facet-value' | translate }}\r\n </div>\r\n <vdr-facet-value-selector\r\n [facets]=\"facets\"\r\n (selectedValuesChange)=\"selectedValues = $event\"\r\n ></vdr-facet-value-selector>\r\n </div>\r\n</div>\r\n\r\n<table class=\"table\" *ngIf=\"state !== 'loading'; else placeholder\">\r\n <tbody>\r\n <tr *ngFor=\"let item of items\">\r\n <td class=\"left align-middle\">\r\n <div>{{ item.name }}</div>\r\n <div *ngIf=\"item.sku\" class=\"sku\">{{ item.sku }}</div>\r\n </td>\r\n <td class=\"left\">\r\n <vdr-facet-value-chip\r\n *ngFor=\"let facetValue of item.facetValues\"\r\n [facetValue]=\"facetValue\"\r\n (remove)=\"removeFacetValue(item, facetValue.id)\"\r\n ></vdr-facet-value-chip>\r\n </td>\r\n </tr>\r\n </tbody>\r\n</table>\r\n\r\n<ng-template #placeholder>\r\n <div class=\"loading\">\r\n <clr-spinner></clr-spinner>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template vdrDialogButtons>\r\n <button type=\"button\" class=\"btn\" (click)=\"cancel()\">{{ 'common.cancel' | translate }}</button>\r\n <button\r\n type=\"submit\"\r\n (click)=\"addFacetValues()\"\r\n [disabled]=\"selectedValues.length === 0 && facetValuesRemoved === false\"\r\n class=\"btn btn-primary\"\r\n >\r\n {{ 'common.update' | translate }}\r\n </button>\r\n</ng-template>\r\n",
|
|
3215
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3216
|
+
styles: [".loading{min-height:25vh;display:flex;justify-content:center;align-items:center}.sku{color:var(--color-text-300)}\n"]
|
|
3217
|
+
},] }
|
|
3218
|
+
];
|
|
3219
|
+
BulkAddFacetValuesDialogComponent.ctorParameters = () => [
|
|
3220
|
+
{ type: DataService },
|
|
3221
|
+
{ type: ChangeDetectorRef }
|
|
3222
|
+
];
|
|
3223
|
+
|
|
2984
3224
|
class CollectionContentsComponent {
|
|
2985
3225
|
constructor(route, router, dataService) {
|
|
2986
3226
|
this.route = route;
|
|
@@ -3090,6 +3330,146 @@ CollectionContentsComponent.propDecorators = {
|
|
|
3090
3330
|
headerTemplate: [{ type: ContentChild, args: [TemplateRef, { static: true },] }]
|
|
3091
3331
|
};
|
|
3092
3332
|
|
|
3333
|
+
const ɵ0$2 = userPermissions => userPermissions.includes(Permission.DeleteCollection) ||
|
|
3334
|
+
userPermissions.includes(Permission.DeleteCatalog), ɵ1$2 = ({ injector, selection, hostComponent, clearSelection }) => {
|
|
3335
|
+
const modalService = injector.get(ModalService);
|
|
3336
|
+
const dataService = injector.get(DataService);
|
|
3337
|
+
const notificationService = injector.get(NotificationService);
|
|
3338
|
+
modalService
|
|
3339
|
+
.dialog({
|
|
3340
|
+
title: marker('catalog.confirm-bulk-delete-collections'),
|
|
3341
|
+
translationVars: {
|
|
3342
|
+
count: selection.length,
|
|
3343
|
+
},
|
|
3344
|
+
buttons: [
|
|
3345
|
+
{ type: 'secondary', label: marker('common.cancel') },
|
|
3346
|
+
{ type: 'danger', label: marker('common.delete'), returnValue: true },
|
|
3347
|
+
],
|
|
3348
|
+
})
|
|
3349
|
+
.pipe(switchMap(response => response
|
|
3350
|
+
? dataService.collection.deleteCollections(unique(selection.map(c => c.id)))
|
|
3351
|
+
: EMPTY))
|
|
3352
|
+
.subscribe(result => {
|
|
3353
|
+
let deleted = 0;
|
|
3354
|
+
const errors = [];
|
|
3355
|
+
for (const item of result.deleteCollections) {
|
|
3356
|
+
if (item.result === DeletionResult.DELETED) {
|
|
3357
|
+
deleted++;
|
|
3358
|
+
}
|
|
3359
|
+
else if (item.message) {
|
|
3360
|
+
errors.push(item.message);
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
if (0 < deleted) {
|
|
3364
|
+
notificationService.success(marker('catalog.notify-bulk-delete-collections-success'), {
|
|
3365
|
+
count: deleted,
|
|
3366
|
+
});
|
|
3367
|
+
}
|
|
3368
|
+
if (0 < errors.length) {
|
|
3369
|
+
notificationService.error(errors.join('\n'));
|
|
3370
|
+
}
|
|
3371
|
+
hostComponent.refresh();
|
|
3372
|
+
clearSelection();
|
|
3373
|
+
});
|
|
3374
|
+
};
|
|
3375
|
+
const deleteCollectionsBulkAction = {
|
|
3376
|
+
location: 'collection-list',
|
|
3377
|
+
label: marker('common.delete'),
|
|
3378
|
+
icon: 'trash',
|
|
3379
|
+
iconClass: 'is-danger',
|
|
3380
|
+
requiresPermission: ɵ0$2,
|
|
3381
|
+
onClick: ɵ1$2,
|
|
3382
|
+
};
|
|
3383
|
+
const ɵ2$2 = userPermissions => userPermissions.includes(Permission.UpdateCatalog) ||
|
|
3384
|
+
userPermissions.includes(Permission.UpdateProduct), ɵ3$2 = ({ injector }) => isMultiChannel(injector.get(DataService)), ɵ4$2 = ({ injector, selection, hostComponent, clearSelection }) => {
|
|
3385
|
+
const modalService = injector.get(ModalService);
|
|
3386
|
+
const dataService = injector.get(DataService);
|
|
3387
|
+
const notificationService = injector.get(NotificationService);
|
|
3388
|
+
modalService
|
|
3389
|
+
.fromComponent(AssignToChannelDialogComponent, {
|
|
3390
|
+
size: 'md',
|
|
3391
|
+
locals: {},
|
|
3392
|
+
})
|
|
3393
|
+
.pipe(switchMap(result => {
|
|
3394
|
+
if (result) {
|
|
3395
|
+
return dataService.collection
|
|
3396
|
+
.assignCollectionsToChannel({
|
|
3397
|
+
collectionIds: selection.map(c => c.id),
|
|
3398
|
+
channelId: result.id,
|
|
3399
|
+
})
|
|
3400
|
+
.pipe(mapTo(result));
|
|
3401
|
+
}
|
|
3402
|
+
else {
|
|
3403
|
+
return EMPTY;
|
|
3404
|
+
}
|
|
3405
|
+
}))
|
|
3406
|
+
.subscribe(result => {
|
|
3407
|
+
notificationService.success(marker('catalog.assign-collections-to-channel-success'), {
|
|
3408
|
+
count: selection.length,
|
|
3409
|
+
channelCode: result.code,
|
|
3410
|
+
});
|
|
3411
|
+
clearSelection();
|
|
3412
|
+
});
|
|
3413
|
+
};
|
|
3414
|
+
const assignCollectionsToChannelBulkAction = {
|
|
3415
|
+
location: 'collection-list',
|
|
3416
|
+
label: marker('catalog.assign-to-channel'),
|
|
3417
|
+
icon: 'layers',
|
|
3418
|
+
requiresPermission: ɵ2$2,
|
|
3419
|
+
isVisible: ɵ3$2,
|
|
3420
|
+
onClick: ɵ4$2,
|
|
3421
|
+
};
|
|
3422
|
+
const ɵ5$2 = userPermissions => userPermissions.includes(Permission.UpdateChannel) ||
|
|
3423
|
+
userPermissions.includes(Permission.UpdateProduct), ɵ6$2 = ({ injector }) => getChannelCodeFromUserStatus(injector.get(DataService)), ɵ7$2 = ({ injector }) => currentChannelIsNotDefault(injector.get(DataService)), ɵ8$2 = ({ injector, selection, hostComponent, clearSelection }) => {
|
|
3424
|
+
const modalService = injector.get(ModalService);
|
|
3425
|
+
const dataService = injector.get(DataService);
|
|
3426
|
+
const notificationService = injector.get(NotificationService);
|
|
3427
|
+
const activeChannelId$ = dataService.client
|
|
3428
|
+
.userStatus()
|
|
3429
|
+
.mapSingle(({ userStatus }) => userStatus.activeChannelId);
|
|
3430
|
+
from(getChannelCodeFromUserStatus(injector.get(DataService)))
|
|
3431
|
+
.pipe(switchMap(({ channelCode }) => modalService.dialog({
|
|
3432
|
+
title: marker('catalog.remove-from-channel'),
|
|
3433
|
+
translationVars: {
|
|
3434
|
+
channelCode,
|
|
3435
|
+
},
|
|
3436
|
+
buttons: [
|
|
3437
|
+
{ type: 'secondary', label: marker('common.cancel') },
|
|
3438
|
+
{
|
|
3439
|
+
type: 'danger',
|
|
3440
|
+
label: marker('common.remove'),
|
|
3441
|
+
returnValue: true,
|
|
3442
|
+
},
|
|
3443
|
+
],
|
|
3444
|
+
})), switchMap(res => res
|
|
3445
|
+
? activeChannelId$.pipe(switchMap(activeChannelId => activeChannelId
|
|
3446
|
+
? dataService.collection.removeCollectionsFromChannel({
|
|
3447
|
+
channelId: activeChannelId,
|
|
3448
|
+
collectionIds: selection.map(c => c.id),
|
|
3449
|
+
})
|
|
3450
|
+
: EMPTY), mapTo(true))
|
|
3451
|
+
: of(false)))
|
|
3452
|
+
.subscribe(removed => {
|
|
3453
|
+
if (removed) {
|
|
3454
|
+
clearSelection();
|
|
3455
|
+
notificationService.success(marker('catalog.notify-remove-collections-from-channel-success'), {
|
|
3456
|
+
count: selection.length,
|
|
3457
|
+
});
|
|
3458
|
+
hostComponent.refresh();
|
|
3459
|
+
}
|
|
3460
|
+
});
|
|
3461
|
+
};
|
|
3462
|
+
const removeCollectionsFromChannelBulkAction = {
|
|
3463
|
+
location: 'collection-list',
|
|
3464
|
+
label: marker('catalog.remove-from-channel'),
|
|
3465
|
+
requiresPermission: ɵ5$2,
|
|
3466
|
+
getTranslationVars: ɵ6$2,
|
|
3467
|
+
icon: 'layers',
|
|
3468
|
+
iconClass: 'is-warning',
|
|
3469
|
+
isVisible: ɵ7$2,
|
|
3470
|
+
onClick: ɵ8$2,
|
|
3471
|
+
};
|
|
3472
|
+
|
|
3093
3473
|
/**
|
|
3094
3474
|
* Builds a tree from an array of nodes which have a parent.
|
|
3095
3475
|
* Based on https://stackoverflow.com/a/31247960/772859, modified to preserve ordering.
|
|
@@ -3207,7 +3587,7 @@ class CollectionTreeComponent {
|
|
|
3207
3587
|
CollectionTreeComponent.decorators = [
|
|
3208
3588
|
{ type: Component, args: [{
|
|
3209
3589
|
selector: 'vdr-collection-tree',
|
|
3210
|
-
template: "<vdr-collection-tree-node\r\n *ngIf=\"collectionTree\"\r\n cdkDropListGroup\r\n [expandAll]=\"expandAll\"\r\n [collectionTree]=\"collectionTree\"\r\n [activeCollectionId]=\"activeCollectionId\"\r\n></vdr-collection-tree-node>\r\n",
|
|
3590
|
+
template: "<vdr-collection-tree-node\r\n *ngIf=\"collectionTree\"\r\n cdkDropListGroup\r\n [expandAll]=\"expandAll\"\r\n [collectionTree]=\"collectionTree\"\r\n [selectionManager]=\"selectionManager\"\r\n [activeCollectionId]=\"activeCollectionId\"\r\n></vdr-collection-tree-node>\r\n",
|
|
3211
3591
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3212
3592
|
styles: [""]
|
|
3213
3593
|
},] }
|
|
@@ -3217,17 +3597,19 @@ CollectionTreeComponent.propDecorators = {
|
|
|
3217
3597
|
activeCollectionId: [{ type: Input }],
|
|
3218
3598
|
expandAll: [{ type: Input }],
|
|
3219
3599
|
expandedIds: [{ type: Input }],
|
|
3600
|
+
selectionManager: [{ type: Input }],
|
|
3220
3601
|
rearrange: [{ type: Output }],
|
|
3221
3602
|
deleteCollection: [{ type: Output }]
|
|
3222
3603
|
};
|
|
3223
3604
|
|
|
3224
3605
|
class CollectionTreeNodeComponent {
|
|
3225
|
-
constructor(parent, root, dataService, router, route) {
|
|
3606
|
+
constructor(parent, root, dataService, router, route, changeDetectorRef) {
|
|
3226
3607
|
this.parent = parent;
|
|
3227
3608
|
this.root = root;
|
|
3228
3609
|
this.dataService = dataService;
|
|
3229
3610
|
this.router = router;
|
|
3230
3611
|
this.route = route;
|
|
3612
|
+
this.changeDetectorRef = changeDetectorRef;
|
|
3231
3613
|
this.depth = 0;
|
|
3232
3614
|
this.expandAll = false;
|
|
3233
3615
|
this.moveListItems = [];
|
|
@@ -3236,6 +3618,7 @@ class CollectionTreeNodeComponent {
|
|
|
3236
3618
|
}
|
|
3237
3619
|
}
|
|
3238
3620
|
ngOnInit() {
|
|
3621
|
+
var _a;
|
|
3239
3622
|
this.parentName = this.collectionTree.name || '<root>';
|
|
3240
3623
|
const permissions$ = this.dataService.client
|
|
3241
3624
|
.userStatus()
|
|
@@ -3243,6 +3626,7 @@ class CollectionTreeNodeComponent {
|
|
|
3243
3626
|
.pipe(shareReplay(1));
|
|
3244
3627
|
this.hasUpdatePermission$ = permissions$.pipe(map(perms => perms.includes(Permission.UpdateCatalog) || perms.includes(Permission.UpdateCollection)));
|
|
3245
3628
|
this.hasDeletePermission$ = permissions$.pipe(map(perms => perms.includes(Permission.DeleteCatalog) || perms.includes(Permission.DeleteCollection)));
|
|
3629
|
+
this.subscription = (_a = this.selectionManager) === null || _a === void 0 ? void 0 : _a.selectionChanges$.subscribe(() => this.changeDetectorRef.markForCheck());
|
|
3246
3630
|
}
|
|
3247
3631
|
ngOnChanges(changes) {
|
|
3248
3632
|
const expandAllChange = changes['expandAll'];
|
|
@@ -3252,6 +3636,10 @@ class CollectionTreeNodeComponent {
|
|
|
3252
3636
|
}
|
|
3253
3637
|
}
|
|
3254
3638
|
}
|
|
3639
|
+
ngOnDestroy() {
|
|
3640
|
+
var _a;
|
|
3641
|
+
(_a = this.subscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
3642
|
+
}
|
|
3255
3643
|
trackByFn(index, item) {
|
|
3256
3644
|
return item.id;
|
|
3257
3645
|
}
|
|
@@ -3314,9 +3702,9 @@ class CollectionTreeNodeComponent {
|
|
|
3314
3702
|
CollectionTreeNodeComponent.decorators = [
|
|
3315
3703
|
{ type: Component, args: [{
|
|
3316
3704
|
selector: 'vdr-collection-tree-node',
|
|
3317
|
-
template: "<div\r\n cdkDropList\r\n class=\"tree-node\"\r\n #dropList\r\n [cdkDropListData]=\"collectionTree\"\r\n [cdkDropListDisabled]=\"!(hasUpdatePermission$ | async)\"\r\n (cdkDropListDropped)=\"drop($event)\"\r\n>\r\n <div\r\n class=\"collection\"\r\n [class.private]=\"collection.isPrivate\"\r\n *ngFor=\"let collection of collectionTree.children; index as i; trackBy: trackByFn\"\r\n cdkDrag\r\n [cdkDragData]=\"collection\"\r\n >\r\n <div\r\n class=\"collection-detail\"\r\n [ngClass]=\"'depth-' + depth\"\r\n [class.active]=\"collection.id === activeCollectionId\"\r\n >\r\n <div class=\"name\">\r\n <button\r\n class=\"icon-button folder-button\"\r\n [disabled]=\"expandAll\"\r\n *ngIf=\"collection.children?.length; else folderSpacer\"\r\n (click)=\"toggleExpanded(collection)\"\r\n >\r\n <clr-icon shape=\"folder\" *ngIf=\"!collection.expanded && !expandAll\"></clr-icon>\r\n <clr-icon shape=\"folder-open\" *ngIf=\"collection.expanded || expandAll\"></clr-icon>\r\n </button>\r\n <ng-template #folderSpacer>\r\n <div class=\"folder-button-spacer\"></div>\r\n </ng-template>\r\n {{ collection.name }}\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <vdr-chip *ngIf=\"collection.isPrivate\">{{ 'catalog.private' | translate }}</vdr-chip>\r\n <a\r\n class=\"btn btn-link btn-sm\"\r\n [routerLink]=\"['./', { contents: collection.id }]\"\r\n queryParamsHandling=\"preserve\"\r\n >\r\n <clr-icon shape=\"view-list\"></clr-icon>\r\n {{ 'catalog.view-contents' | translate }}\r\n </a>\r\n <a class=\"btn btn-link btn-sm\" [routerLink]=\"['/catalog/collections/', collection.id]\">\r\n <clr-icon shape=\"edit\"></clr-icon>\r\n {{ 'common.edit' | translate }}\r\n </a>\r\n <div class=\"drag-handle\" cdkDragHandle *vdrIfPermissions=\"['UpdateCatalog', 'UpdateCollection']\">\r\n <clr-icon shape=\"drag-handle\" size=\"24\"></clr-icon>\r\n </div>\r\n <vdr-dropdown>\r\n <button class=\"icon-button\" vdrDropdownTrigger (click)=\"getMoveListItems(collection)\">\r\n <clr-icon shape=\"ellipsis-vertical\"></clr-icon>\r\n </button>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n <a\r\n class=\"dropdown-item\"\r\n [routerLink]=\"['./', 'create', { parentId: collection.id }]\"\r\n *vdrIfPermissions=\"['CreateCatalog', 'CreateCollection']\"\r\n >\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.create-new-collection' | translate }}\r\n </a>\r\n <div class=\"dropdown-divider\"></div>\r\n <button\r\n type=\"button\"\r\n vdrDropdownItem\r\n [disabled]=\"i === 0 || !(hasUpdatePermission$ | async)\"\r\n (click)=\"moveUp(collection, i)\"\r\n >\r\n <clr-icon shape=\"caret up\"></clr-icon>\r\n {{ 'catalog.move-up' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n vdrDropdownItem\r\n [disabled]=\"\r\n i === collectionTree.children.length - 1 || !(hasUpdatePermission$ | async)\r\n \"\r\n (click)=\"moveDown(collection, i)\"\r\n >\r\n <clr-icon shape=\"caret down\"></clr-icon>\r\n {{ 'catalog.move-down' | translate }}\r\n </button>\r\n <h4 class=\"dropdown-header\">{{ 'catalog.move-to' | translate }}</h4>\r\n <button\r\n type=\"button\"\r\n vdrDropdownItem\r\n *ngFor=\"let item of moveListItems\"\r\n (click)=\"move(collection, item.id)\"\r\n [disabled]=\"!(hasUpdatePermission$ | async)\"\r\n >\r\n <div class=\"move-to-item\">\r\n <div class=\"move-icon\">\r\n <clr-icon shape=\"child-arrow\"></clr-icon>\r\n </div>\r\n <div class=\"path\">\r\n {{ item.path }}\r\n </div>\r\n </div>\r\n </button>\r\n <div class=\"dropdown-divider\"></div>\r\n <button\r\n class=\"button\"\r\n vdrDropdownItem\r\n (click)=\"delete(collection.id)\"\r\n [disabled]=\"!(hasDeletePermission$ | async)\"\r\n >\r\n <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon>\r\n {{ 'common.delete' | translate }}\r\n </button>\r\n </vdr-dropdown-menu>\r\n </vdr-dropdown>\r\n </div>\r\n <vdr-collection-tree-node\r\n *ngIf=\"collection.expanded || expandAll\"\r\n [expandAll]=\"expandAll\"\r\n [collectionTree]=\"collection\"\r\n [activeCollectionId]=\"activeCollectionId\"\r\n ></vdr-collection-tree-node>\r\n </div>\r\n</div>\r\n",
|
|
3705
|
+
template: "<div\r\n cdkDropList\r\n class=\"tree-node\"\r\n #dropList\r\n [cdkDropListData]=\"collectionTree\"\r\n [cdkDropListDisabled]=\"!(hasUpdatePermission$ | async)\"\r\n (cdkDropListDropped)=\"drop($event)\"\r\n>\r\n <div\r\n class=\"collection\"\r\n [class.private]=\"collection.isPrivate\"\r\n *ngFor=\"let collection of collectionTree.children; index as i; trackBy: trackByFn\"\r\n cdkDrag\r\n [cdkDragData]=\"collection\"\r\n >\r\n <div\r\n class=\"collection-detail\"\r\n [ngClass]=\"'depth-' + depth\"\r\n [class.active]=\"collection.id === activeCollectionId\"\r\n >\r\n <div>\r\n <input\r\n type=\"checkbox\"\r\n clrCheckbox\r\n [checked]=\"selectionManager.isSelected(collection)\"\r\n (click)=\"selectionManager.toggleSelection(collection, $event)\"\r\n />\r\n </div>\r\n <div class=\"name\">\r\n <button\r\n class=\"icon-button folder-button\"\r\n [disabled]=\"expandAll\"\r\n *ngIf=\"collection.children?.length; else folderSpacer\"\r\n (click)=\"toggleExpanded(collection)\"\r\n >\r\n <clr-icon shape=\"folder\" *ngIf=\"!collection.expanded && !expandAll\"></clr-icon>\r\n <clr-icon shape=\"folder-open\" *ngIf=\"collection.expanded || expandAll\"></clr-icon>\r\n </button>\r\n <ng-template #folderSpacer>\r\n <div class=\"folder-button-spacer\"></div>\r\n </ng-template>\r\n {{ collection.name }}\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <vdr-chip *ngIf=\"collection.isPrivate\">{{ 'catalog.private' | translate }}</vdr-chip>\r\n <a\r\n class=\"btn btn-link btn-sm\"\r\n [routerLink]=\"['./', { contents: collection.id }]\"\r\n queryParamsHandling=\"preserve\"\r\n >\r\n <clr-icon shape=\"view-list\"></clr-icon>\r\n {{ 'catalog.view-contents' | translate }}\r\n </a>\r\n <a class=\"btn btn-link btn-sm\" [routerLink]=\"['/catalog/collections/', collection.id]\">\r\n <clr-icon shape=\"edit\"></clr-icon>\r\n {{ 'common.edit' | translate }}\r\n </a>\r\n <div class=\"drag-handle\" cdkDragHandle *vdrIfPermissions=\"['UpdateCatalog', 'UpdateCollection']\">\r\n <clr-icon shape=\"drag-handle\" size=\"24\"></clr-icon>\r\n </div>\r\n <vdr-dropdown>\r\n <button class=\"icon-button\" vdrDropdownTrigger (click)=\"getMoveListItems(collection)\">\r\n <clr-icon shape=\"ellipsis-vertical\"></clr-icon>\r\n </button>\r\n <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n <a\r\n class=\"dropdown-item\"\r\n [routerLink]=\"['./', 'create', { parentId: collection.id }]\"\r\n *vdrIfPermissions=\"['CreateCatalog', 'CreateCollection']\"\r\n >\r\n <clr-icon shape=\"plus\"></clr-icon>\r\n {{ 'catalog.create-new-collection' | translate }}\r\n </a>\r\n <div class=\"dropdown-divider\"></div>\r\n <button\r\n type=\"button\"\r\n vdrDropdownItem\r\n [disabled]=\"i === 0 || !(hasUpdatePermission$ | async)\"\r\n (click)=\"moveUp(collection, i)\"\r\n >\r\n <clr-icon shape=\"caret up\"></clr-icon>\r\n {{ 'catalog.move-up' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n vdrDropdownItem\r\n [disabled]=\"\r\n i === collectionTree.children.length - 1 || !(hasUpdatePermission$ | async)\r\n \"\r\n (click)=\"moveDown(collection, i)\"\r\n >\r\n <clr-icon shape=\"caret down\"></clr-icon>\r\n {{ 'catalog.move-down' | translate }}\r\n </button>\r\n <h4 class=\"dropdown-header\">{{ 'catalog.move-to' | translate }}</h4>\r\n <button\r\n type=\"button\"\r\n vdrDropdownItem\r\n *ngFor=\"let item of moveListItems\"\r\n (click)=\"move(collection, item.id)\"\r\n [disabled]=\"!(hasUpdatePermission$ | async)\"\r\n >\r\n <div class=\"move-to-item\">\r\n <div class=\"move-icon\">\r\n <clr-icon shape=\"child-arrow\"></clr-icon>\r\n </div>\r\n <div class=\"path\">\r\n {{ item.path }}\r\n </div>\r\n </div>\r\n </button>\r\n <div class=\"dropdown-divider\"></div>\r\n <button\r\n class=\"button\"\r\n vdrDropdownItem\r\n (click)=\"delete(collection.id)\"\r\n [disabled]=\"!(hasDeletePermission$ | async)\"\r\n >\r\n <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon>\r\n {{ 'common.delete' | translate }}\r\n </button>\r\n </vdr-dropdown-menu>\r\n </vdr-dropdown>\r\n </div>\r\n <vdr-collection-tree-node\r\n *ngIf=\"collection.expanded || expandAll\"\r\n [expandAll]=\"expandAll\"\r\n [collectionTree]=\"collection\"\r\n [activeCollectionId]=\"activeCollectionId\"\r\n [selectionManager]=\"selectionManager\"\r\n ></vdr-collection-tree-node>\r\n </div>\r\n</div>\r\n",
|
|
3318
3706
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3319
|
-
styles: [":host{display:block}.collection{background-color:var(--
|
|
3707
|
+
styles: [":host{display:block}.collection{background-color:var(--clr-table-bgcolor);border-radius:var(--clr-global-borderradius);font-size:.65rem;transition:transform .25s cubic-bezier(0,0,.2,1);margin-bottom:2px;border-left:2px solid transparent;transition:border-left-color .2s}.collection.private{background-color:var(--color-component-bg-200)}.collection .collection-detail{padding:6px 12px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--color-component-border-100)}.collection .collection-detail.active{background-color:var(--clr-global-selection-color)}.collection .collection-detail.depth-1{padding-left:36px}.collection .collection-detail.depth-2{padding-left:60px}.collection .collection-detail.depth-3{padding-left:84px}.collection .collection-detail.depth-4{padding-left:108px}.collection .collection-detail .folder-button-spacer{display:inline-block;width:28px}.tree-node{display:block;background-color:var(--clr-table-bgcolor);border-radius:var(--clr-global-borderradius);overflow:hidden}.tree-node.cdk-drop-list-dragging>.collection{border-left-color:var(--color-primary-300)}.drag-placeholder{min-height:120px;background-color:var(--color-component-bg-300);transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-list.cdk-drop-list-dragging .tree-node:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.move-to-item{display:flex;white-space:normal;align-items:baseline}.move-to-item .move-icon{flex:none;margin-right:3px}.move-to-item .path{line-height:18px}\n"]
|
|
3320
3708
|
},] }
|
|
3321
3709
|
];
|
|
3322
3710
|
CollectionTreeNodeComponent.ctorParameters = () => [
|
|
@@ -3324,12 +3712,215 @@ CollectionTreeNodeComponent.ctorParameters = () => [
|
|
|
3324
3712
|
{ type: CollectionTreeComponent },
|
|
3325
3713
|
{ type: DataService },
|
|
3326
3714
|
{ type: Router },
|
|
3327
|
-
{ type: ActivatedRoute }
|
|
3715
|
+
{ type: ActivatedRoute },
|
|
3716
|
+
{ type: ChangeDetectorRef }
|
|
3328
3717
|
];
|
|
3329
3718
|
CollectionTreeNodeComponent.propDecorators = {
|
|
3330
3719
|
collectionTree: [{ type: Input }],
|
|
3331
3720
|
activeCollectionId: [{ type: Input }],
|
|
3332
|
-
expandAll: [{ type: Input }]
|
|
3721
|
+
expandAll: [{ type: Input }],
|
|
3722
|
+
selectionManager: [{ type: Input }]
|
|
3723
|
+
};
|
|
3724
|
+
|
|
3725
|
+
const ɵ0$1 = userPermissions => userPermissions.includes(Permission.DeleteFacet) ||
|
|
3726
|
+
userPermissions.includes(Permission.DeleteCatalog), ɵ1$1 = ({ injector, selection, hostComponent, clearSelection }) => {
|
|
3727
|
+
const modalService = injector.get(ModalService);
|
|
3728
|
+
const dataService = injector.get(DataService);
|
|
3729
|
+
const notificationService = injector.get(NotificationService);
|
|
3730
|
+
function showModalAndDelete(facetIds, message) {
|
|
3731
|
+
return modalService
|
|
3732
|
+
.dialog({
|
|
3733
|
+
title: marker('catalog.confirm-bulk-delete-facets'),
|
|
3734
|
+
translationVars: {
|
|
3735
|
+
count: selection.length,
|
|
3736
|
+
},
|
|
3737
|
+
size: message ? 'lg' : 'md',
|
|
3738
|
+
body: message,
|
|
3739
|
+
buttons: [
|
|
3740
|
+
{ type: 'secondary', label: marker('common.cancel') },
|
|
3741
|
+
{
|
|
3742
|
+
type: 'danger',
|
|
3743
|
+
label: message ? marker('common.force-delete') : marker('common.delete'),
|
|
3744
|
+
returnValue: true,
|
|
3745
|
+
},
|
|
3746
|
+
],
|
|
3747
|
+
})
|
|
3748
|
+
.pipe(switchMap(res => res
|
|
3749
|
+
? dataService.facet
|
|
3750
|
+
.deleteFacets(facetIds, !!message)
|
|
3751
|
+
.pipe(map(res2 => res2.deleteFacets))
|
|
3752
|
+
: of([])));
|
|
3753
|
+
}
|
|
3754
|
+
showModalAndDelete(unique(selection.map(f => f.id)))
|
|
3755
|
+
.pipe(switchMap(result => {
|
|
3756
|
+
var _a;
|
|
3757
|
+
let deletedCount = 0;
|
|
3758
|
+
const errors = [];
|
|
3759
|
+
const errorIds = [];
|
|
3760
|
+
let i = 0;
|
|
3761
|
+
for (const item of result) {
|
|
3762
|
+
if (item.result === DeletionResult.DELETED) {
|
|
3763
|
+
deletedCount++;
|
|
3764
|
+
}
|
|
3765
|
+
else if (item.message) {
|
|
3766
|
+
errors.push(item.message);
|
|
3767
|
+
errorIds.push((_a = selection[i]) === null || _a === void 0 ? void 0 : _a.id);
|
|
3768
|
+
}
|
|
3769
|
+
i++;
|
|
3770
|
+
}
|
|
3771
|
+
if (0 < errorIds.length) {
|
|
3772
|
+
return showModalAndDelete(errorIds, errors.join('\n')).pipe(map(result2 => {
|
|
3773
|
+
const deletedCount2 = result2.filter(r => r.result === DeletionResult.DELETED).length;
|
|
3774
|
+
return deletedCount + deletedCount2;
|
|
3775
|
+
}));
|
|
3776
|
+
}
|
|
3777
|
+
else {
|
|
3778
|
+
return of(deletedCount);
|
|
3779
|
+
}
|
|
3780
|
+
}))
|
|
3781
|
+
.subscribe(deletedCount => {
|
|
3782
|
+
if (deletedCount) {
|
|
3783
|
+
hostComponent.refresh();
|
|
3784
|
+
clearSelection();
|
|
3785
|
+
notificationService.success(marker('catalog.notify-bulk-delete-facets-success'), {
|
|
3786
|
+
count: deletedCount,
|
|
3787
|
+
});
|
|
3788
|
+
}
|
|
3789
|
+
});
|
|
3790
|
+
};
|
|
3791
|
+
const deleteFacetsBulkAction = {
|
|
3792
|
+
location: 'facet-list',
|
|
3793
|
+
label: marker('common.delete'),
|
|
3794
|
+
icon: 'trash',
|
|
3795
|
+
iconClass: 'is-danger',
|
|
3796
|
+
requiresPermission: ɵ0$1,
|
|
3797
|
+
onClick: ɵ1$1,
|
|
3798
|
+
};
|
|
3799
|
+
const ɵ2$1 = userPermissions => userPermissions.includes(Permission.UpdateFacet) ||
|
|
3800
|
+
userPermissions.includes(Permission.UpdateCatalog), ɵ3$1 = ({ injector }) => isMultiChannel(injector.get(DataService)), ɵ4$1 = ({ injector, selection, hostComponent, clearSelection }) => {
|
|
3801
|
+
const modalService = injector.get(ModalService);
|
|
3802
|
+
const dataService = injector.get(DataService);
|
|
3803
|
+
const notificationService = injector.get(NotificationService);
|
|
3804
|
+
modalService
|
|
3805
|
+
.fromComponent(AssignToChannelDialogComponent, {
|
|
3806
|
+
size: 'md',
|
|
3807
|
+
locals: {},
|
|
3808
|
+
})
|
|
3809
|
+
.pipe(switchMap(result => {
|
|
3810
|
+
if (result) {
|
|
3811
|
+
return dataService.facet
|
|
3812
|
+
.assignFacetsToChannel({
|
|
3813
|
+
facetIds: selection.map(f => f.id),
|
|
3814
|
+
channelId: result.id,
|
|
3815
|
+
})
|
|
3816
|
+
.pipe(mapTo(result));
|
|
3817
|
+
}
|
|
3818
|
+
else {
|
|
3819
|
+
return EMPTY;
|
|
3820
|
+
}
|
|
3821
|
+
}))
|
|
3822
|
+
.subscribe(result => {
|
|
3823
|
+
notificationService.success(marker('catalog.assign-facets-to-channel-success'), {
|
|
3824
|
+
count: selection.length,
|
|
3825
|
+
channelCode: result.code,
|
|
3826
|
+
});
|
|
3827
|
+
clearSelection();
|
|
3828
|
+
});
|
|
3829
|
+
};
|
|
3830
|
+
const assignFacetsToChannelBulkAction = {
|
|
3831
|
+
location: 'facet-list',
|
|
3832
|
+
label: marker('catalog.assign-to-channel'),
|
|
3833
|
+
icon: 'layers',
|
|
3834
|
+
requiresPermission: ɵ2$1,
|
|
3835
|
+
isVisible: ɵ3$1,
|
|
3836
|
+
onClick: ɵ4$1,
|
|
3837
|
+
};
|
|
3838
|
+
const ɵ5$1 = ({ injector }) => getChannelCodeFromUserStatus(injector.get(DataService)), ɵ6$1 = userPermissions => userPermissions.includes(Permission.UpdateFacet) ||
|
|
3839
|
+
userPermissions.includes(Permission.UpdateCatalog), ɵ7$1 = ({ injector }) => currentChannelIsNotDefault(injector.get(DataService)), ɵ8$1 = ({ injector, selection, hostComponent, clearSelection }) => {
|
|
3840
|
+
const modalService = injector.get(ModalService);
|
|
3841
|
+
const dataService = injector.get(DataService);
|
|
3842
|
+
const notificationService = injector.get(NotificationService);
|
|
3843
|
+
const activeChannelId$ = dataService.client
|
|
3844
|
+
.userStatus()
|
|
3845
|
+
.mapSingle(({ userStatus }) => userStatus.activeChannelId);
|
|
3846
|
+
function showModalAndDelete(facetIds, message) {
|
|
3847
|
+
return modalService
|
|
3848
|
+
.dialog({
|
|
3849
|
+
title: marker('catalog.remove-from-channel'),
|
|
3850
|
+
translationVars: {
|
|
3851
|
+
count: selection.length,
|
|
3852
|
+
},
|
|
3853
|
+
size: message ? 'lg' : 'md',
|
|
3854
|
+
body: message,
|
|
3855
|
+
buttons: [
|
|
3856
|
+
{ type: 'secondary', label: marker('common.cancel') },
|
|
3857
|
+
{
|
|
3858
|
+
type: 'danger',
|
|
3859
|
+
label: message ? marker('common.force-remove') : marker('common.remove'),
|
|
3860
|
+
returnValue: true,
|
|
3861
|
+
},
|
|
3862
|
+
],
|
|
3863
|
+
})
|
|
3864
|
+
.pipe(switchMap(res => res
|
|
3865
|
+
? activeChannelId$.pipe(switchMap(activeChannelId => activeChannelId
|
|
3866
|
+
? dataService.facet.removeFacetsFromChannel({
|
|
3867
|
+
channelId: activeChannelId,
|
|
3868
|
+
facetIds,
|
|
3869
|
+
force: !!message,
|
|
3870
|
+
})
|
|
3871
|
+
: EMPTY), map(res2 => res2.removeFacetsFromChannel))
|
|
3872
|
+
: EMPTY));
|
|
3873
|
+
}
|
|
3874
|
+
showModalAndDelete(unique(selection.map(f => f.id)))
|
|
3875
|
+
.pipe(switchMap(result => {
|
|
3876
|
+
var _a;
|
|
3877
|
+
let removedCount = selection.length;
|
|
3878
|
+
const errors = [];
|
|
3879
|
+
const errorIds = [];
|
|
3880
|
+
let i = 0;
|
|
3881
|
+
for (const item of result) {
|
|
3882
|
+
if (item.__typename === 'FacetInUseError') {
|
|
3883
|
+
errors.push(item.message);
|
|
3884
|
+
errorIds.push((_a = selection[i]) === null || _a === void 0 ? void 0 : _a.id);
|
|
3885
|
+
removedCount--;
|
|
3886
|
+
}
|
|
3887
|
+
i++;
|
|
3888
|
+
}
|
|
3889
|
+
if (0 < errorIds.length) {
|
|
3890
|
+
return showModalAndDelete(errorIds, errors.join('\n')).pipe(map(result2 => {
|
|
3891
|
+
const notRemovedCount = result2.filter(r => r.__typename === 'FacetInUseError').length;
|
|
3892
|
+
return selection.length - notRemovedCount;
|
|
3893
|
+
}));
|
|
3894
|
+
}
|
|
3895
|
+
else {
|
|
3896
|
+
return of(removedCount);
|
|
3897
|
+
}
|
|
3898
|
+
}), switchMap(removedCount => removedCount
|
|
3899
|
+
? getChannelCodeFromUserStatus(dataService).then(({ channelCode }) => ({
|
|
3900
|
+
channelCode,
|
|
3901
|
+
removedCount,
|
|
3902
|
+
}))
|
|
3903
|
+
: EMPTY))
|
|
3904
|
+
.subscribe(({ removedCount, channelCode }) => {
|
|
3905
|
+
if (removedCount) {
|
|
3906
|
+
hostComponent.refresh();
|
|
3907
|
+
clearSelection();
|
|
3908
|
+
notificationService.success(marker('catalog.notify-remove-facets-from-channel-success'), {
|
|
3909
|
+
count: removedCount,
|
|
3910
|
+
channelCode,
|
|
3911
|
+
});
|
|
3912
|
+
}
|
|
3913
|
+
});
|
|
3914
|
+
};
|
|
3915
|
+
const removeFacetsFromChannelBulkAction = {
|
|
3916
|
+
location: 'facet-list',
|
|
3917
|
+
label: marker('catalog.remove-from-channel'),
|
|
3918
|
+
getTranslationVars: ɵ5$1,
|
|
3919
|
+
icon: 'layers',
|
|
3920
|
+
iconClass: 'is-warning',
|
|
3921
|
+
requiresPermission: ɵ6$1,
|
|
3922
|
+
isVisible: ɵ7$1,
|
|
3923
|
+
onClick: ɵ8$1,
|
|
3333
3924
|
};
|
|
3334
3925
|
|
|
3335
3926
|
const DEFAULT_VARIANT_CODE = '__DEFAULT_VARIANT__';
|
|
@@ -3565,6 +4156,171 @@ OptionValueInputComponent.propDecorators = {
|
|
|
3565
4156
|
disabled: [{ type: Input }]
|
|
3566
4157
|
};
|
|
3567
4158
|
|
|
4159
|
+
const ɵ0 = userPermissions => userPermissions.includes(Permission.DeleteProduct) ||
|
|
4160
|
+
userPermissions.includes(Permission.DeleteCatalog), ɵ1 = ({ injector, selection, hostComponent, clearSelection }) => {
|
|
4161
|
+
const modalService = injector.get(ModalService);
|
|
4162
|
+
const dataService = injector.get(DataService);
|
|
4163
|
+
const notificationService = injector.get(NotificationService);
|
|
4164
|
+
modalService
|
|
4165
|
+
.dialog({
|
|
4166
|
+
title: marker('catalog.confirm-bulk-delete-products'),
|
|
4167
|
+
translationVars: {
|
|
4168
|
+
count: selection.length,
|
|
4169
|
+
},
|
|
4170
|
+
buttons: [
|
|
4171
|
+
{ type: 'secondary', label: marker('common.cancel') },
|
|
4172
|
+
{ type: 'danger', label: marker('common.delete'), returnValue: true },
|
|
4173
|
+
],
|
|
4174
|
+
})
|
|
4175
|
+
.pipe(switchMap(response => response
|
|
4176
|
+
? dataService.product.deleteProducts(unique(selection.map(p => p.productId)))
|
|
4177
|
+
: EMPTY))
|
|
4178
|
+
.subscribe(result => {
|
|
4179
|
+
let deleted = 0;
|
|
4180
|
+
const errors = [];
|
|
4181
|
+
for (const item of result.deleteProducts) {
|
|
4182
|
+
if (item.result === DeletionResult.DELETED) {
|
|
4183
|
+
deleted++;
|
|
4184
|
+
}
|
|
4185
|
+
else if (item.message) {
|
|
4186
|
+
errors.push(item.message);
|
|
4187
|
+
}
|
|
4188
|
+
}
|
|
4189
|
+
if (0 < deleted) {
|
|
4190
|
+
notificationService.success(marker('catalog.notify-bulk-delete-products-success'), {
|
|
4191
|
+
count: deleted,
|
|
4192
|
+
});
|
|
4193
|
+
}
|
|
4194
|
+
if (0 < errors.length) {
|
|
4195
|
+
notificationService.error(errors.join('\n'));
|
|
4196
|
+
}
|
|
4197
|
+
hostComponent.refresh();
|
|
4198
|
+
clearSelection();
|
|
4199
|
+
});
|
|
4200
|
+
};
|
|
4201
|
+
const deleteProductsBulkAction = {
|
|
4202
|
+
location: 'product-list',
|
|
4203
|
+
label: marker('common.delete'),
|
|
4204
|
+
icon: 'trash',
|
|
4205
|
+
iconClass: 'is-danger',
|
|
4206
|
+
requiresPermission: ɵ0,
|
|
4207
|
+
onClick: ɵ1,
|
|
4208
|
+
};
|
|
4209
|
+
const ɵ2 = userPermissions => userPermissions.includes(Permission.UpdateCatalog) ||
|
|
4210
|
+
userPermissions.includes(Permission.UpdateProduct), ɵ3 = ({ injector }) => isMultiChannel(injector.get(DataService)), ɵ4 = ({ injector, selection, hostComponent, clearSelection }) => {
|
|
4211
|
+
const modalService = injector.get(ModalService);
|
|
4212
|
+
const dataService = injector.get(DataService);
|
|
4213
|
+
const notificationService = injector.get(NotificationService);
|
|
4214
|
+
modalService
|
|
4215
|
+
.fromComponent(AssignProductsToChannelDialogComponent, {
|
|
4216
|
+
size: 'lg',
|
|
4217
|
+
locals: {
|
|
4218
|
+
productIds: unique(selection.map(p => p.productId)),
|
|
4219
|
+
currentChannelIds: [],
|
|
4220
|
+
},
|
|
4221
|
+
})
|
|
4222
|
+
.subscribe(result => {
|
|
4223
|
+
if (result) {
|
|
4224
|
+
clearSelection();
|
|
4225
|
+
}
|
|
4226
|
+
});
|
|
4227
|
+
};
|
|
4228
|
+
const assignProductsToChannelBulkAction = {
|
|
4229
|
+
location: 'product-list',
|
|
4230
|
+
label: marker('catalog.assign-to-channel'),
|
|
4231
|
+
icon: 'layers',
|
|
4232
|
+
requiresPermission: ɵ2,
|
|
4233
|
+
isVisible: ɵ3,
|
|
4234
|
+
onClick: ɵ4,
|
|
4235
|
+
};
|
|
4236
|
+
const ɵ5 = userPermissions => userPermissions.includes(Permission.UpdateChannel) ||
|
|
4237
|
+
userPermissions.includes(Permission.UpdateProduct), ɵ6 = ({ injector }) => getChannelCodeFromUserStatus(injector.get(DataService)), ɵ7 = ({ injector }) => currentChannelIsNotDefault(injector.get(DataService)), ɵ8 = ({ injector, selection, hostComponent, clearSelection }) => {
|
|
4238
|
+
const modalService = injector.get(ModalService);
|
|
4239
|
+
const dataService = injector.get(DataService);
|
|
4240
|
+
const notificationService = injector.get(NotificationService);
|
|
4241
|
+
const activeChannelId$ = dataService.client
|
|
4242
|
+
.userStatus()
|
|
4243
|
+
.mapSingle(({ userStatus }) => userStatus.activeChannelId);
|
|
4244
|
+
from(getChannelCodeFromUserStatus(injector.get(DataService)))
|
|
4245
|
+
.pipe(switchMap(({ channelCode }) => modalService.dialog({
|
|
4246
|
+
title: marker('catalog.remove-from-channel'),
|
|
4247
|
+
translationVars: {
|
|
4248
|
+
channelCode,
|
|
4249
|
+
},
|
|
4250
|
+
buttons: [
|
|
4251
|
+
{ type: 'secondary', label: marker('common.cancel') },
|
|
4252
|
+
{
|
|
4253
|
+
type: 'danger',
|
|
4254
|
+
label: marker('common.remove'),
|
|
4255
|
+
returnValue: true,
|
|
4256
|
+
},
|
|
4257
|
+
],
|
|
4258
|
+
})), switchMap(res => res
|
|
4259
|
+
? activeChannelId$.pipe(switchMap(activeChannelId => activeChannelId
|
|
4260
|
+
? dataService.product.removeProductsFromChannel({
|
|
4261
|
+
channelId: activeChannelId,
|
|
4262
|
+
productIds: selection.map(p => p.productId),
|
|
4263
|
+
})
|
|
4264
|
+
: EMPTY), mapTo(true))
|
|
4265
|
+
: of(false)))
|
|
4266
|
+
.subscribe(removed => {
|
|
4267
|
+
if (removed) {
|
|
4268
|
+
clearSelection();
|
|
4269
|
+
notificationService.success(marker('common.notify-remove-products-from-channel-success'), {
|
|
4270
|
+
count: selection.length,
|
|
4271
|
+
});
|
|
4272
|
+
setTimeout(() => hostComponent.refresh(), 1000);
|
|
4273
|
+
}
|
|
4274
|
+
});
|
|
4275
|
+
};
|
|
4276
|
+
const removeProductsFromChannelBulkAction = {
|
|
4277
|
+
location: 'product-list',
|
|
4278
|
+
label: marker('catalog.remove-from-channel'),
|
|
4279
|
+
requiresPermission: ɵ5,
|
|
4280
|
+
getTranslationVars: ɵ6,
|
|
4281
|
+
icon: 'layers',
|
|
4282
|
+
iconClass: 'is-warning',
|
|
4283
|
+
isVisible: ɵ7,
|
|
4284
|
+
onClick: ɵ8,
|
|
4285
|
+
};
|
|
4286
|
+
const ɵ9 = userPermissions => userPermissions.includes(Permission.UpdateCatalog) ||
|
|
4287
|
+
userPermissions.includes(Permission.UpdateProduct), ɵ10 = ({ injector, selection, hostComponent, clearSelection }) => {
|
|
4288
|
+
const modalService = injector.get(ModalService);
|
|
4289
|
+
const dataService = injector.get(DataService);
|
|
4290
|
+
const notificationService = injector.get(NotificationService);
|
|
4291
|
+
const mode = hostComponent.groupByProduct ? 'product' : 'variant';
|
|
4292
|
+
const ids = mode === 'product'
|
|
4293
|
+
? unique(selection.map(p => p.productId))
|
|
4294
|
+
: unique(selection.map(p => p.productVariantId));
|
|
4295
|
+
return dataService.facet
|
|
4296
|
+
.getAllFacets()
|
|
4297
|
+
.mapSingle(data => data.facets.items)
|
|
4298
|
+
.pipe(switchMap(facets => modalService.fromComponent(BulkAddFacetValuesDialogComponent, {
|
|
4299
|
+
size: 'xl',
|
|
4300
|
+
locals: {
|
|
4301
|
+
facets,
|
|
4302
|
+
mode,
|
|
4303
|
+
ids,
|
|
4304
|
+
},
|
|
4305
|
+
})))
|
|
4306
|
+
.subscribe(result => {
|
|
4307
|
+
if (result) {
|
|
4308
|
+
notificationService.success(marker('common.notify-bulk-update-success'), {
|
|
4309
|
+
count: selection.length,
|
|
4310
|
+
entity: mode === 'product' ? 'Products' : 'ProductVariants',
|
|
4311
|
+
});
|
|
4312
|
+
clearSelection();
|
|
4313
|
+
}
|
|
4314
|
+
});
|
|
4315
|
+
};
|
|
4316
|
+
const assignFacetValuesToProductsBulkAction = {
|
|
4317
|
+
location: 'product-list',
|
|
4318
|
+
label: marker('catalog.edit-facet-values'),
|
|
4319
|
+
icon: 'tag',
|
|
4320
|
+
requiresPermission: ɵ9,
|
|
4321
|
+
onClick: ɵ10,
|
|
4322
|
+
};
|
|
4323
|
+
|
|
3568
4324
|
class UpdateProductOptionDialogComponent {
|
|
3569
4325
|
constructor() {
|
|
3570
4326
|
this.updateVariantName = true;
|
|
@@ -3800,7 +4556,7 @@ class ProductVariantsListComponent {
|
|
|
3800
4556
|
ProductVariantsListComponent.decorators = [
|
|
3801
4557
|
{ type: Component, args: [{
|
|
3802
4558
|
selector: 'vdr-product-variants-list',
|
|
3803
|
-
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",
|
|
4559
|
+
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: { channelCode: channel.code }\"\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",
|
|
3804
4560
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3805
4561
|
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;flex-wrap:wrap;max-height:110px;overflow-y:auto}.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"]
|
|
3806
4562
|
},] }
|
|
@@ -3973,8 +4729,23 @@ const CATALOG_COMPONENTS = [
|
|
|
3973
4729
|
AssetDetailComponent,
|
|
3974
4730
|
ConfirmVariantDeletionDialogComponent,
|
|
3975
4731
|
ProductOptionsEditorComponent,
|
|
4732
|
+
BulkAddFacetValuesDialogComponent,
|
|
4733
|
+
AssignToChannelDialogComponent,
|
|
3976
4734
|
];
|
|
3977
4735
|
class CatalogModule {
|
|
4736
|
+
constructor(bulkActionRegistryService) {
|
|
4737
|
+
this.bulkActionRegistryService = bulkActionRegistryService;
|
|
4738
|
+
bulkActionRegistryService.registerBulkAction(assignFacetValuesToProductsBulkAction);
|
|
4739
|
+
bulkActionRegistryService.registerBulkAction(assignProductsToChannelBulkAction);
|
|
4740
|
+
bulkActionRegistryService.registerBulkAction(removeProductsFromChannelBulkAction);
|
|
4741
|
+
bulkActionRegistryService.registerBulkAction(deleteProductsBulkAction);
|
|
4742
|
+
bulkActionRegistryService.registerBulkAction(assignFacetsToChannelBulkAction);
|
|
4743
|
+
bulkActionRegistryService.registerBulkAction(removeFacetsFromChannelBulkAction);
|
|
4744
|
+
bulkActionRegistryService.registerBulkAction(deleteFacetsBulkAction);
|
|
4745
|
+
bulkActionRegistryService.registerBulkAction(assignCollectionsToChannelBulkAction);
|
|
4746
|
+
bulkActionRegistryService.registerBulkAction(removeCollectionsFromChannelBulkAction);
|
|
4747
|
+
bulkActionRegistryService.registerBulkAction(deleteCollectionsBulkAction);
|
|
4748
|
+
}
|
|
3978
4749
|
}
|
|
3979
4750
|
CatalogModule.decorators = [
|
|
3980
4751
|
{ type: NgModule, args: [{
|
|
@@ -3982,6 +4753,9 @@ CatalogModule.decorators = [
|
|
|
3982
4753
|
exports: [...CATALOG_COMPONENTS],
|
|
3983
4754
|
declarations: [...CATALOG_COMPONENTS],
|
|
3984
4755
|
},] }
|
|
4756
|
+
];
|
|
4757
|
+
CatalogModule.ctorParameters = () => [
|
|
4758
|
+
{ type: BulkActionRegistryService }
|
|
3985
4759
|
];
|
|
3986
4760
|
|
|
3987
4761
|
// This file was generated by the build-public-api.ts script
|
|
@@ -3990,5 +4764,5 @@ CatalogModule.decorators = [
|
|
|
3990
4764
|
* Generated bundle index. Do not edit.
|
|
3991
4765
|
*/
|
|
3992
4766
|
|
|
3993
|
-
export { ApplyFacetDialogComponent, AssetDetailComponent, AssetListComponent, AssetResolver, AssetsComponent, AssignProductsToChannelDialogComponent, CatalogModule, CollectionContentsComponent, CollectionDetailComponent, CollectionListComponent, CollectionResolver, CollectionTreeComponent, CollectionTreeNodeComponent, ConfirmVariantDeletionDialogComponent, FacetDetailComponent, FacetListComponent, FacetResolver, GenerateProductVariantsComponent, GeneratedVariant, OPTION_VALUE_INPUT_VALUE_ACCESSOR, OptionValueInputComponent, ProductDetailComponent, ProductDetailService, ProductListComponent, ProductOptionsEditorComponent, ProductResolver, ProductVariantsEditorComponent, ProductVariantsListComponent, ProductVariantsResolver, ProductVariantsTableComponent, UpdateProductOptionDialogComponent, VariantPriceDetailComponent, arrayToTree, assetBreadcrumb,
|
|
4767
|
+
export { ApplyFacetDialogComponent, AssetDetailComponent, AssetListComponent, AssetResolver, AssetsComponent, AssignProductsToChannelDialogComponent, AssignToChannelDialogComponent, BulkAddFacetValuesDialogComponent, CatalogModule, CollectionContentsComponent, CollectionDetailComponent, CollectionListComponent, CollectionResolver, CollectionTreeComponent, CollectionTreeNodeComponent, ConfirmVariantDeletionDialogComponent, FacetDetailComponent, FacetListComponent, FacetResolver, GET_PRODUCTS_WITH_FACET_VALUES_BY_IDS, GET_VARIANTS_WITH_FACET_VALUES_BY_IDS, GenerateProductVariantsComponent, GeneratedVariant, OPTION_VALUE_INPUT_VALUE_ACCESSOR, OptionValueInputComponent, ProductDetailComponent, ProductDetailService, ProductListComponent, ProductOptionsEditorComponent, ProductResolver, ProductVariantsEditorComponent, ProductVariantsListComponent, ProductVariantsResolver, ProductVariantsTableComponent, UPDATE_PRODUCTS_BULK, UPDATE_VARIANTS_BULK, UpdateProductOptionDialogComponent, VariantPriceDetailComponent, arrayToTree, assetBreadcrumb, assignCollectionsToChannelBulkAction, assignFacetValuesToProductsBulkAction, assignFacetsToChannelBulkAction, assignProductsToChannelBulkAction, catalogRoutes, collectionBreadcrumb, deleteCollectionsBulkAction, deleteFacetsBulkAction, deleteProductsBulkAction, facetBreadcrumb, productBreadcrumb, productOptionsEditorBreadcrumb, productVariantEditorBreadcrumb, removeCollectionsFromChannelBulkAction, removeFacetsFromChannelBulkAction, removeProductsFromChannelBulkAction, replaceLast, ɵ10 };
|
|
3994
4768
|
//# sourceMappingURL=vendure-admin-ui-catalog.js.map
|