{"version":3,"file":"static/js/31802bf5ad9c84c280a8.bundle.js","mappings":"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","sources":["webpack://Msdyn365.Commerce.Online/./src/actions/get-organization-customer.ts?79c2","webpack://Msdyn365.Commerce.Online/./src/actions/get-product-unit-of-measure-options.action.ts?bc1e","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/actions/base-collection-action.ts?11e2","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/actions/get-cached-price-for-product-search-results.ts?029f","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/actions/get-full-products-by-collection.ts?8637","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/actions/get-mapped-search-configuration.ts?6b32","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/actions/get-refiners-for-collection.ts?5d9b","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/actions/get-inventory-refiners.ts?275a","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/actions/refiner-utils.ts?04ba","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/actions/url-utils.ts?6503","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/choice-summary.tsx?f410","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/error-message.tsx?3c52","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/feature-search-result-item.tsx?eefa","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/link.tsx?b255","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/modal.tsx?c4c9","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/product-search-result-items.tsx?573e","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/separator.tsx?f88a","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/title.tsx?e5ce","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/range-refine-item-input.tsx?6940","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/range-refine-item.tsx?1286","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/refine-item.tsx?7edb","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/refine-submenu.tsx?776f","webpack://Msdyn365.Commerce.Online/./src/modules/dlvry-search-result-container/components/utilities.ts?c7b3","webpack://Msdyn365.Commerce.Online/./src/shared-utils/attributes/on-buy-access-validator.ts?4b31","webpack://Msdyn365.Commerce.Online/./src/shared-utils/cookie-utilities.ts?6237"],"sourcesContent":["import { createObservableDataAction, IActionContext, IAction, ICreateActionContext, IGeneric, IAny, ICommerceApiSettings } from '@msdyn365-commerce/core';\r\nimport { CacheType, callActionOrExecute, Customer, DataServiceQuery, IActionInput, IDataServiceRequest } from \"@msdyn365-commerce/retail-proxy\";\r\nimport * as Entities from '@msdyn365-commerce/retail-proxy/dist/Entities/CommerceModels.g';\r\n\r\nexport class GetOrganizationCustomerInput implements IActionInput {\r\n private readonly user: string | undefined;\r\n private readonly query: DataServiceQuery;\r\n\r\n constructor(apiSettings: ICommerceApiSettings, user: string) {\r\n this.user = user;\r\n\r\n this.query = new DataServiceQuery();\r\n }\r\n\r\n public getDataServiceRequest = (): IDataServiceRequest => {\r\n return this.query.createDataServiceRequestForOperation(\r\n 'GetOrganizationCustomer',\r\n false,\r\n Entities.CustomerClass,\r\n 'false',\r\n {\r\n bypassCache: 'get',\r\n returnEntity: 'Entities.CustomerClass'\r\n },\r\n {}\r\n );\r\n };\r\n\r\n public shouldCacheOutput = (): boolean => false;\r\n\r\n public getCacheKey = () => `OrganizationCustomer-${this.user}`;\r\n public getCacheObjectType = () => 'OrganizationCustomer';\r\n public dataCacheType = (): CacheType => 'request';\r\n}\r\n\r\nconst createInput = (inputData: ICreateActionContext>): GetOrganizationCustomerInput => {\r\n const { user } = inputData.requestContext;\r\n return new GetOrganizationCustomerInput(inputData.requestContext.apiSettings, user.customerAccountNumber ?? \"\");\r\n};\r\n\r\nexport const getOrganizationCustomerAction = async (input: GetOrganizationCustomerInput, ctx: IActionContext): Promise => {\r\n if (!ctx.requestContext.user.isAuthenticated) {\r\n return {};\r\n }\r\n var customer = await callActionOrExecute(input.getDataServiceRequest(), ctx);\r\n return customer;\r\n};\r\n\r\nexport const getOrganizationCustomer = createObservableDataAction({\r\n id: 'src/actions/get-organization-customer',\r\n action: >getOrganizationCustomerAction,\r\n input: createInput\r\n});\r\n\r\nexport default getOrganizationCustomer;\r\n","import { callActionOrExecute, DataServiceQuery, IContext, IDataServiceRequest, IQueryResultSettings } from \"@msdyn365-commerce/retail-proxy\";\r\nimport * as Entities from '@msdyn365-commerce/retail-proxy/dist/Entities/CommerceModels.g';\r\nimport * as Types from '@msdyn365-commerce/retail-proxy/dist/Entities/CommerceTypes.g';\r\n\r\nfunction getProductUnitOfMeasureOptionsQuery(): DataServiceQuery {\r\n return new DataServiceQuery();\r\n}\r\n\r\n\r\nexport function getProductUnitOfMeasureOptionsInput(\r\n queryResultSettings: IQueryResultSettings, productIds:\r\n number[]\r\n): IDataServiceRequest {\r\n const query = getProductUnitOfMeasureOptionsQuery().resultSettings(queryResultSettings);\r\n query.top(10000);\r\n return query.createDataServiceRequestForOperation(\r\n 'GetProductUnitOfMeasureOptions',\r\n true, Entities.UnitOfMeasureConversionClass,\r\n 'true',\r\n { bypassCache: 'none', returnEntity: 'Entities.UnitOfMeasureConversion' },\r\n {\r\n productIds: productIds\r\n }\r\n );\r\n}\r\n\r\nexport async function getProductUnitOfMeasureOptionsAsync(context: IContext, productIds: number[]): Promise {\r\n const request = getProductUnitOfMeasureOptionsInput(\r\n context.queryResultSettings || {}, productIds);\r\n const conversions = await callActionOrExecute(request, context.callerContext);\r\n return conversions;\r\n}","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { CacheType, getCatalogId, IActionInput, IAny, ICommerceApiSettings, ICreateActionContext, IGeneric } from '@msdyn365-commerce/core';\r\nimport { IProductRefinerHierarchy } from '@msdyn365-commerce/commerce-entities';\r\nimport {\r\n convertToString,\r\n ChannelInventoryConfiguration,\r\n IQueryResultSettings,\r\n ProductRefinerValue,\r\n SortColumn\r\n} from '@msdyn365-commerce/retail-proxy';\r\nimport { generateCacheKey, QueryResultSettingsProxy } from '@msdyn365-commerce-modules/retail-actions';\r\nimport { toJS } from 'mobx';\r\n\r\nimport { hydrateRefinersFromUrl } from './url-utils';\r\n\r\n/**\r\n * Export listPageType.\r\n */\r\nexport type listPageType = 'Category' | 'Search' | 'Unknown';\r\n\r\n/**\r\n * Get include attributes from config.\r\n * @param inputData - ICreateActionContext.\r\n * @returns Boolean.\r\n */\r\nfunction getIncludeAttributes(inputData: ICreateActionContext, IGeneric>): boolean {\r\n if (process.env.NODE_ENV === 'development' && process.env.ENABLE_CLOUD_SEARCH?.toLowerCase() !== 'true') {\r\n return false;\r\n }\r\n\r\n if (inputData && inputData.config && inputData.config.includeAttributes !== undefined && inputData.config.includeAttributes === true) {\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Get updateRefinerPanel from config.\r\n * @param inputData - ICreateActionContext.\r\n * @returns Boolean.\r\n */\r\nfunction getUpdateRefinerPanel(inputData: ICreateActionContext, IGeneric>): boolean {\r\n return !!inputData.config?.updateRefinerPanel;\r\n}\r\n\r\n/**\r\n * BaseCollection Action Input.\r\n */\r\nexport class BaseCollectionInput implements IActionInput {\r\n public pageType: listPageType;\r\n\r\n public category: number | undefined;\r\n\r\n public searchText: string | undefined;\r\n\r\n public refiners: ProductRefinerValue[];\r\n\r\n public queryResultSettings: IQueryResultSettings;\r\n\r\n public apiSettings: ICommerceApiSettings;\r\n\r\n public includeAttributes: boolean | undefined;\r\n\r\n public locale?: string;\r\n\r\n public isUpdateRefinerPanel?: boolean;\r\n\r\n public catalogId?: number;\r\n\r\n public channelInventoryConfiguration?: ChannelInventoryConfiguration;\r\n\r\n public inventoryRefiner?: IProductRefinerHierarchy;\r\n\r\n public constructor(\r\n pageType: listPageType,\r\n apiSettings: ICommerceApiSettings,\r\n queryResultSettings: IQueryResultSettings,\r\n refiners: ProductRefinerValue[],\r\n category: number | undefined,\r\n searchText: string | undefined,\r\n includeAttributes: boolean | undefined,\r\n isUpdateRefinerPanel?: boolean | undefined,\r\n locale?: string,\r\n catalogId?: number,\r\n channelInventoryConfiguration?: ChannelInventoryConfiguration,\r\n inventoryRefiner?: IProductRefinerHierarchy\r\n ) {\r\n this.pageType = pageType;\r\n this.apiSettings = apiSettings;\r\n this.category = category;\r\n this.searchText = searchText;\r\n this.queryResultSettings = queryResultSettings;\r\n this.refiners = refiners;\r\n this.includeAttributes = includeAttributes;\r\n this.isUpdateRefinerPanel = isUpdateRefinerPanel;\r\n this.locale = locale;\r\n this.catalogId = catalogId ?? 0;\r\n this.channelInventoryConfiguration = channelInventoryConfiguration;\r\n this.inventoryRefiner = inventoryRefiner;\r\n }\r\n\r\n public getCacheKey = () => {\r\n const queryResultSettings = {\r\n ...this.queryResultSettings.Paging,\r\n ...toJS(this.queryResultSettings.Sorting)\r\n };\r\n\r\n const cacheKey = generateCacheKey(\r\n this.apiSettings,\r\n { key: 'PageType', value: this.pageType },\r\n { key: 'Category', value: this.category },\r\n { key: 'SearchText', value: this.searchText },\r\n { key: 'CatalogId', value: this.catalogId },\r\n {\r\n key: 'Refiners',\r\n value: this.refiners.map(\r\n refiner =>\r\n `RefinerRecordId:${refiner.RefinerRecordId}-LeftValueBoundString:${refiner.LeftValueBoundString ||\r\n ''}-RightValueBoundString:${refiner.RightValueBoundString || ''}`\r\n )\r\n },\r\n { key: 'QueryResultSettings', value: convertToString(queryResultSettings) },\r\n { key: 'Locale', value: this.locale }\r\n );\r\n return cacheKey;\r\n };\r\n\r\n public getCacheObjectType = () => 'CollectionActionResult';\r\n\r\n public dataCacheType = (): CacheType => 'request';\r\n}\r\n\r\n// TODO: Create a data model here or import one to capture the response of the action\r\nexport interface IGetFullProductsByCollectionData {\r\n text: string;\r\n}\r\n\r\nexport type CollectionClassConstructor = new (\r\n pageType: listPageType,\r\n apiSettings: ICommerceApiSettings,\r\n queryResultSettings: IQueryResultSettings,\r\n refiners: ProductRefinerValue[],\r\n category: number | undefined,\r\n searchText: string | undefined,\r\n includeAttributes: boolean | undefined,\r\n isUpdateRefinerPanel?: boolean | undefined,\r\n locale?: string,\r\n catalogId?: number,\r\n channelInventoryConfiguration?: ChannelInventoryConfiguration,\r\n inventoryRefiner?: IProductRefinerHierarchy\r\n) => BaseCollectionInput;\r\n\r\n/**\r\n * TODO: Use this function to create the input required to make the action call.\r\n * @param args\r\n * @param inputClassConstuctor\r\n */\r\nexport const createBaseCollectionInput = (\r\n args: ICreateActionContext,\r\n inputClassConstuctor: CollectionClassConstructor\r\n): BaseCollectionInput => {\r\n const pageType =\r\n args.requestContext.urlTokens.pageType === 'Category' || (args.requestContext.query && args.requestContext.query.categoryId)\r\n ? 'Category'\r\n : 'Search';\r\n\r\n const queryResultSettings = QueryResultSettingsProxy.fromInputData(args).QueryResultSettings;\r\n const queryRefiners = hydrateRefinersFromUrl(args.requestContext);\r\n const includeAttributes = getIncludeAttributes(args);\r\n const isUpdateRefinerPanel = getUpdateRefinerPanel(args);\r\n const catalogId = getCatalogId(args.requestContext);\r\n\r\n if (args.requestContext.query && args.requestContext.query.sorting) {\r\n queryResultSettings.Sorting = { Columns: JSON.parse(decodeURIComponent(args.requestContext.query.sorting)) };\r\n }\r\n\r\n if (pageType === 'Category') {\r\n return new inputClassConstuctor(\r\n pageType,\r\n args.requestContext.apiSettings,\r\n queryResultSettings,\r\n queryRefiners,\r\n +(args.requestContext.urlTokens.itemId || (args.requestContext.query && args.requestContext.query.categoryId) || 0),\r\n args.requestContext.query?.q,\r\n includeAttributes,\r\n isUpdateRefinerPanel,\r\n args.requestContext.locale,\r\n catalogId\r\n );\r\n } else if (pageType === 'Search' && args.requestContext.query && args.requestContext.query.q && !args.requestContext.query.recommendation) {\r\n return new inputClassConstuctor(\r\n pageType,\r\n args.requestContext.apiSettings,\r\n queryResultSettings,\r\n queryRefiners,\r\n undefined,\r\n args.requestContext.query.q,\r\n includeAttributes,\r\n isUpdateRefinerPanel,\r\n args.requestContext.locale,\r\n catalogId\r\n );\r\n } else if (pageType === 'Search' && args.requestContext.query && args.requestContext.query.recommendation) {\r\n let searchText = '';\r\n if (args.requestContext.query.productId) {\r\n searchText = JSON.stringify({\r\n ProductId: args.requestContext.query.productId,\r\n Recommendation: args.requestContext.query.recommendation,\r\n SearchText: args.requestContext.query.q\r\n });\r\n } else {\r\n searchText = JSON.stringify({ Recommendation: args.requestContext.query.recommendation, SearchText: args.requestContext.query.q });\r\n }\r\n return new inputClassConstuctor(\r\n pageType,\r\n args.requestContext.apiSettings,\r\n queryResultSettings,\r\n queryRefiners,\r\n undefined,\r\n searchText,\r\n includeAttributes,\r\n isUpdateRefinerPanel,\r\n args.requestContext.locale,\r\n catalogId\r\n );\r\n } else if (pageType === 'Search' && args.requestContext.query && args.requestContext.query.discountIds) {\r\n const searchText = JSON.stringify({ DiscountIds: args.requestContext.query.discountIds });\r\n return new inputClassConstuctor(\r\n pageType,\r\n args.requestContext.apiSettings,\r\n queryResultSettings,\r\n queryRefiners,\r\n undefined,\r\n searchText,\r\n includeAttributes,\r\n isUpdateRefinerPanel,\r\n args.requestContext.locale,\r\n catalogId\r\n );\r\n }\r\n\r\n throw new Error('[getFullProductsForCollection]Unable to create input');\r\n};\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\nimport { CacheType, createObservableDataAction, getCatalogId, IAction, IActionContext, IActionInput } from '@msdyn365-commerce/core';\r\nimport { ProductSearchResult, ProjectionDomain } from '@msdyn365-commerce/retail-proxy';\r\nimport { ArrayExtensions, QueryResultSettingsProxy } from '@msdyn365-commerce-modules/retail-actions';\r\nimport { ProductSearchResultExt } from '../components';\r\nimport { getActivePricesAsync } from '@msdyn365-commerce/retail-proxy/dist/DataActions/ProductsDataActions.g';\r\nimport { getDiscountBadge } from '../../../shared-utils/badge-utils';\r\n\r\n/**\r\n * Input class for the GetCachedPriceForProductSearchResult Data Action.\r\n */\r\nexport class CachedPriceForProductSearchResultInput implements IActionInput {\r\n public products: ProductSearchResultExt[];\r\n\r\n public constructor(products: ProductSearchResult[] | ProductSearchResultExt[]) {\r\n this.products = products;\r\n }\r\n\r\n /**\r\n * Get the cache key.\r\n * @returns The cache key.\r\n */\r\n public getCacheKey = (): string => `CachedPriceForProductSearchResult-${JSON.stringify(this.products)}`;\r\n\r\n /**\r\n * Get the cache object type.\r\n * @returns The cache object type.\r\n */\r\n public getCacheObjectType = (): string => 'ProductSearchResult';\r\n\r\n /**\r\n * Define the data cache type.\r\n * @returns The cache type.\r\n */\r\n public dataCacheType = (): CacheType => 'none';\r\n}\r\n\r\n/**\r\n * The createInput method for the GetCachedPriceForProductSearchResultDataAction.\r\n * @param products -- The product search result.\r\n * @returns The input.\r\n */\r\nexport const createCachedActivePriceForProductSearchResultInput = (products: ProductSearchResult[] | ProductSearchResultExt[]): CachedPriceForProductSearchResultInput => {\r\n return new CachedPriceForProductSearchResultInput(products);\r\n};\r\n\r\n/**\r\n * The Action Method for the GetCachedPriceForProductSearchResult Data Action\r\n * Gets the active price for product search result via the getActivePrice RetailServer API.\r\n * @param input -- The data input.\r\n * @param context -- The action context.\r\n * @returns The product search result updated with price.\r\n */\r\nexport async function getCachedPriceForProductSearchResultAction(\r\n input: CachedPriceForProductSearchResultInput,\r\n context: IActionContext\r\n): Promise {\r\n let productRecIds: number[];\r\n if (ArrayExtensions.hasElements(input.products)) {\r\n productRecIds = input.products.map(product => product.RecordId);\r\n } else {\r\n return Promise.resolve([]);\r\n }\r\n\r\n const catalogId = getCatalogId(context.requestContext);\r\n\r\n const projectDomain: ProjectionDomain = { ChannelId: +context.requestContext.apiSettings.channelId, CatalogId: catalogId };\r\n const priceZero = 0;\r\n\r\n try {\r\n const productPrices = await getActivePricesAsync({ callerContext: context, queryResultSettings: QueryResultSettingsProxy.getPagingFromInputDataOrDefaultValue(context) },\r\n projectDomain,\r\n productRecIds,\r\n new Date(),\r\n null,\r\n null,\r\n true,\r\n false,\r\n false);\r\n\r\n const productResults = input.products.map(product => {\r\n const activePrice = productPrices.find(price => price.ProductId === product.RecordId);\r\n if (activePrice) {\r\n product.Badge = getDiscountBadge(activePrice);\r\n product.Price = activePrice.CustomerContextualPrice ?? product.Price;\r\n product.BasePrice = Math.max(\r\n activePrice.BasePrice ?? priceZero,\r\n activePrice.TradeAgreementPrice ?? priceZero,\r\n activePrice.AdjustedPrice ?? priceZero\r\n );\r\n product.ProductPrice = activePrice;\r\n product.PrefetchedPrice = true;\r\n }\r\n return product;\r\n });\r\n\r\n return Promise.resolve(productResults);\r\n } catch (error) {\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- existing error type.\r\n context.telemetry.exception(error);\r\n context.telemetry.debug('[getCachedPriceForProductSearchResultAction]Error executing action');\r\n throw new Error('[getCachedPriceForProductSearchResultAction]Error executing action');\r\n }\r\n}\r\n\r\n/**\r\n * The getPriceForProductSearchResult data action.\r\n */\r\nexport const getCachedPriceForProductSearchResultDataAction = createObservableDataAction({\r\n id: '@msdyn365-commerce-modules/retail-actions/get-cached-price-for-product-search-result',\r\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- existing pattern.\r\n action: >getCachedPriceForProductSearchResultAction,\r\n input: createCachedActivePriceForProductSearchResultInput\r\n});\r\n\r\nexport default getCachedPriceForProductSearchResultDataAction;\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport {\r\n CacheType,\r\n createObservableDataAction,\r\n GetCustomerInput,\r\n IAction,\r\n IActionContext,\r\n IActionInput,\r\n ICreateActionContext\r\n} from '@msdyn365-commerce/core';\r\nimport { AsyncResult, ChannelInventoryConfiguration, ProductSearchCriteria, ProductSearchResult } from '@msdyn365-commerce/retail-proxy';\r\nimport { getProductPromotionsAsync, searchByCriteriaAsync } from '@msdyn365-commerce/retail-proxy/dist/DataActions/ProductsDataActions.g';\r\nimport { getInventoryConfigurationAsync } from '@msdyn365-commerce/retail-proxy/dist/DataActions/StoreOperationsDataActions.g';\r\nimport {\r\n ArrayExtensions,\r\n generateProductImageUrl,\r\n getCustomer,\r\n InventoryLevels\r\n} from '@msdyn365-commerce-modules/retail-actions';\r\n\r\nimport { BaseCollectionInput, createBaseCollectionInput } from './base-collection-action';\r\nimport { getInventorySortableRefinerValue } from '.';\r\nimport { addAlcoholRefiner as addAlcoholRefinerAsync, addAllAttributeRefiners, addOrUpdateZeroPriceRefiner, shouldFilterAlcohol } from './refiner-utils';\r\nimport getCachedPriceForProductSearchResultDataAction, { CachedPriceForProductSearchResultInput } from './get-cached-price-for-product-search-results';\r\nimport { ProductSearchResultExt } from '../components';\r\n\r\n/**\r\n * GetFullProductsByCollection Action Input.\r\n */\r\nexport class GetFullProductsByCollectionInput extends BaseCollectionInput implements IActionInput {\r\n /**\r\n * The cache object type.\r\n * @returns The cache object type.\r\n */\r\n public getCacheObjectType = (): string => 'FullProductSearchResult';\r\n\r\n /**\r\n * The data cache type.\r\n * @returns The data cache type.\r\n */\r\n public dataCacheType = (): CacheType => {\r\n // return 'none';\r\n if (\r\n this.pageType !== 'Category' ||\r\n (this.refiners && this.refiners.length > 0) ||\r\n (this.queryResultSettings &&\r\n this.queryResultSettings.Sorting &&\r\n this.queryResultSettings.Sorting.Columns &&\r\n this.queryResultSettings.Sorting.Columns.length > 0)\r\n ) {\r\n return 'request';\r\n }\r\n return 'application';\r\n };\r\n}\r\n\r\n/**\r\n * This setting defines inventory filtering options.\r\n */\r\nexport enum ProductListInventoryFilteringOptions {\r\n /**\r\n * Filter out all products out of stock.\r\n */\r\n HideOOS = 'hideOOS',\r\n\r\n /**\r\n * Sort products by availability, OOS goes last.\r\n */\r\n SortOOS = 'sortOOS',\r\n\r\n /**\r\n * No filtering selected.\r\n */\r\n Default = 'default'\r\n}\r\n\r\n/**\r\n * The full product search result with count interface.\r\n */\r\nexport interface IFullProductsSearchResultsWithCount {\r\n products: ProductSearchResultExt[];\r\n count: number;\r\n channelInventoryConfigurationId?: number;\r\n inventoryAwareSortableAttributeId?: number;\r\n}\r\n\r\n/**\r\n * CreateInput function which creates and actionInput used to fetch products for a list page.\r\n * @param args - The API arguments.\r\n * @returns IActionInput - The action input.\r\n */\r\nconst createInput = (args: ICreateActionContext<{ itemsPerPage: number; includedAttributes: boolean | undefined }>): IActionInput => {\r\n const input = createBaseCollectionInput(args, GetFullProductsByCollectionInput);\r\n\r\n // Set Top\r\n if (input.queryResultSettings.Paging && args.config) {\r\n input.queryResultSettings.Paging.Top = args.config.itemsPerPage || 1;\r\n }\r\n\r\n // Set Skip\r\n if (input.queryResultSettings.Paging && args.requestContext.query && args.requestContext.query.skip) {\r\n input.queryResultSettings.Paging.Skip = +args.requestContext.query.skip;\r\n }\r\n\r\n input.queryResultSettings.count = true;\r\n\r\n return input;\r\n};\r\n\r\n/**\r\n * Returns list of products based on inventory information.\r\n * @param productSearchResults - The products.\r\n * @param context - The context.\r\n * @param metadataCount - The metadata count.\r\n * @param channelInventoryConfiguration - The channel inventory configuration.\r\n * @returns List of product based on the inventory information.\r\n */\r\nexport async function returnProducts(\r\n productSearchResults: ProductSearchResult[],\r\n context: IActionContext,\r\n metadataCount: number | undefined,\r\n channelInventoryConfiguration?: ChannelInventoryConfiguration\r\n): Promise {\r\n const defaultProductCount: number = 0;\r\n\r\n const productSearchResultsWithImages = productSearchResults.map(productSearchResult => {\r\n const newImageUrl = generateProductImageUrl(productSearchResult, context.requestContext.apiSettings);\r\n\r\n if (newImageUrl) {\r\n productSearchResult.PrimaryImageUrl = newImageUrl;\r\n }\r\n\r\n return productSearchResult;\r\n });\r\n\r\n // If inventory level is threshold or inventory check is disabled then return the list of products without the inventory configuration\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- read config file.\r\n if (\r\n context.requestContext.app.config.inventoryLevel === InventoryLevels.threshold ||\r\n context.requestContext.app.config.enableStockCheck === false\r\n ) {\r\n return {\r\n products: productSearchResultsWithImages,\r\n count: metadataCount ?? defaultProductCount\r\n };\r\n }\r\n\r\n const mappedProducts = productSearchResultsWithImages.map(productSearchResult => {\r\n if (ArrayExtensions.hasElements(productSearchResult.AttributeValues)) {\r\n for (const element of productSearchResult.AttributeValues) {\r\n if (\r\n channelInventoryConfiguration &&\r\n element.RecordId !== undefined &&\r\n element.RecordId === channelInventoryConfiguration.InventoryProductAttributeRecordId &&\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- read config file.\r\n context.requestContext.app.config.inventoryRanges !== 'all' &&\r\n element.TextValue !== channelInventoryConfiguration.InventoryOutOfStockAttributeValueText\r\n ) {\r\n // If same RecordId then it means that is the Inventory attribute\r\n // Based on the inventory range (and filtering options), the inventory label will be displayed\r\n // If Inventory range is 'All' then in stock and out of stock labels are shown, else only OOS\r\n // if the text value is different that the channelInventoryConfiguration.InventoryOutOfStockAttributeValueText then is in stock\r\n element.TextValue = '';\r\n }\r\n }\r\n }\r\n\r\n return productSearchResult;\r\n });\r\n\r\n return {\r\n products: mappedProducts,\r\n count: metadataCount ?? defaultProductCount,\r\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- check config.\r\n channelInventoryConfigurationId: channelInventoryConfiguration\r\n ? channelInventoryConfiguration.InventoryProductAttributeRecordId\r\n : undefined,\r\n inventoryAwareSortableAttributeId: channelInventoryConfiguration\r\n ? channelInventoryConfiguration.ProductAvailabilitySortableAttributeRecordId\r\n : undefined\r\n };\r\n}\r\n\r\n/**\r\n * Action function to fetch products for a list page.\r\n * @param input - The input.\r\n * @param context - The context.\r\n * @returns IFullProductsSearchResultsWithCount - The full product search result with count.\r\n */\r\n// eslint-disable-next-line complexity -- ignore the complexity.\r\nasync function action(input: GetFullProductsByCollectionInput, context: IActionContext): Promise {\r\n let promise: AsyncResult;\r\n let channelInventoryConfigurationPromise: AsyncResult;\r\n let searchProductId;\r\n const searchCriteriaInput: ProductSearchCriteria = {};\r\n searchCriteriaInput.Context = { ChannelId: context.requestContext.apiSettings.channelId, CatalogId: input.catalogId };\r\n // Decouple searchCriteriaInput.Refinement from input.refiners to avoid input.refiners being modified below\r\n searchCriteriaInput.Refinement = JSON.parse(JSON.stringify(input.refiners.slice()));\r\n if (process.env.NODE_ENV === 'development' && process.env.ENABLE_CLOUD_SEARCH?.toLowerCase() !== 'true') {\r\n searchCriteriaInput.IncludeAttributes = false;\r\n } else {\r\n searchCriteriaInput.IncludeAttributes = input.includeAttributes;\r\n }\r\n searchCriteriaInput.SkipVariantExpansion = true;\r\n searchCriteriaInput.SearchCondition = input.searchText;\r\n const defaultNumber: number = 0;\r\n\r\n // Fix mobx arrays that got turned to objects\r\n for (let index = 0; index < searchCriteriaInput.Refinement!.length; index++) {\r\n const element = searchCriteriaInput.Refinement![index];\r\n\r\n if (element.ExtensionProperties && typeof element.ExtensionProperties === 'object') {\r\n element.ExtensionProperties = JSON.parse(JSON.stringify(input.refiners[index].ExtensionProperties?.slice()));\r\n }\r\n }\r\n\r\n searchCriteriaInput.Refinement = addOrUpdateZeroPriceRefiner(context, searchCriteriaInput.Refinement);\r\n\r\n if (shouldFilterAlcohol(context)) {\r\n await addAlcoholRefinerAsync(context, searchCriteriaInput);\r\n }\r\n\r\n await addAllAttributeRefiners(context, searchCriteriaInput);\r\n\r\n if (input.channelInventoryConfiguration) {\r\n channelInventoryConfigurationPromise = AsyncResult.resolve(input.channelInventoryConfiguration);\r\n } else {\r\n channelInventoryConfigurationPromise = getInventoryConfigurationAsync({ callerContext: context });\r\n }\r\n const channelInventoryConfiguration = await channelInventoryConfigurationPromise;\r\n\r\n // Replace InventoryProductAttribute with boolean refiner.\r\n // Because the value of InventoryProductAttribute is different from language to language since it's string type.\r\n // The cached old inventory refiner value may be hit when customer switch language which will lead to \"no products found\" issue.\r\n const inventoryRefiner = searchCriteriaInput.Refinement.find(\r\n refiner => refiner.RefinerRecordId === channelInventoryConfiguration?.InventoryProductAttributeRecordId\r\n );\r\n if (inventoryRefiner) {\r\n searchCriteriaInput.Refinement = searchCriteriaInput.Refinement.filter(\r\n refiner => refiner.RefinerRecordId !== channelInventoryConfiguration?.InventoryProductAttributeRecordId\r\n );\r\n\r\n const isInStockRefiner =\r\n inventoryRefiner.LeftValueBoundString !== channelInventoryConfiguration?.InventoryOutOfStockAttributeValueText &&\r\n inventoryRefiner.RightValueBoundString !== channelInventoryConfiguration?.InventoryOutOfStockAttributeValueText;\r\n const inventoryRefinerValue = getInventorySortableRefinerValue(channelInventoryConfiguration, isInStockRefiner);\r\n\r\n const isInventoryRefinerValueExist = searchCriteriaInput.Refinement.some(\r\n refiner => refiner.RefinerRecordId === inventoryRefinerValue?.RefinerRecordId\r\n );\r\n if (!isInventoryRefinerValueExist && inventoryRefinerValue) {\r\n searchCriteriaInput.Refinement.push(inventoryRefinerValue);\r\n }\r\n }\r\n\r\n if (context.requestContext.app.config?.productListInventoryDisplay === ProductListInventoryFilteringOptions.HideOOS) {\r\n const isInStock = true;\r\n const inventoryInStockRefinerValue = getInventorySortableRefinerValue(channelInventoryConfiguration, isInStock);\r\n\r\n const isInventoryInStockRefinerValueExist = searchCriteriaInput.Refinement.some(\r\n refiner => refiner.RefinerRecordId === inventoryInStockRefinerValue?.RefinerRecordId\r\n );\r\n if (!isInventoryInStockRefinerValueExist && inventoryInStockRefinerValue) {\r\n searchCriteriaInput.Refinement.push(inventoryInStockRefinerValue);\r\n }\r\n }\r\n\r\n if (context.requestContext.app.config?.prioritySortingAttribute) {\r\n const prioritySortingAttribute = context.requestContext.app.config.prioritySortingAttribute as string;\r\n\r\n // Check if the priority sorting attribute only has digits. If not skip this\r\n if (prioritySortingAttribute.match(/^\\d+$/)) {\r\n input.queryResultSettings.Sorting = input.queryResultSettings.Sorting ?? {};\r\n input.queryResultSettings.Sorting.Columns = input.queryResultSettings.Sorting.Columns ?? [];\r\n const priorityColumnName = `Attr_${prioritySortingAttribute}`;\r\n const isPriorityAttributeExist = input.queryResultSettings.Sorting.Columns.some(column => column.ColumnName === priorityColumnName);\r\n if (!isPriorityAttributeExist) {\r\n input.queryResultSettings.Sorting.Columns.push({\r\n ColumnName: priorityColumnName,\r\n IsDescending: true\r\n });\r\n }\r\n }\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- app configs are of generic type\r\n if (\r\n context.requestContext.app.config?.productListInventoryDisplay === ProductListInventoryFilteringOptions.SortOOS &&\r\n channelInventoryConfiguration.ProductAvailabilitySortableAttributeRecordId\r\n ) {\r\n input.queryResultSettings.Sorting = input.queryResultSettings.Sorting ?? {};\r\n input.queryResultSettings.Sorting.Columns = input.queryResultSettings.Sorting.Columns ?? [];\r\n const sortColumnName = `Attr_${channelInventoryConfiguration.ProductAvailabilitySortableAttributeRecordId}`;\r\n const isSortAttributeExist = input.queryResultSettings.Sorting.Columns.some(column => column.ColumnName === sortColumnName);\r\n if (!isSortAttributeExist) {\r\n input.queryResultSettings.Sorting.Columns.push({\r\n ColumnName: sortColumnName,\r\n IsDescending: true\r\n });\r\n }\r\n }\r\n\r\n if (input.pageType === 'Category' || context.requestContext.query?.categoryId) {\r\n if (input.category) {\r\n searchCriteriaInput.CategoryIds = [input.category || defaultNumber];\r\n promise = searchByCriteriaAsync(\r\n {\r\n callerContext: context,\r\n queryResultSettings: input.queryResultSettings\r\n },\r\n searchCriteriaInput\r\n );\r\n } else {\r\n throw new Error('[GetFullProductsForCollection]Category Page Detected, but no global categoryId found');\r\n }\r\n } else if (input.searchText && context.requestContext.query?.q && !context.requestContext.query.recommendation) {\r\n searchCriteriaInput.SearchCondition = input.searchText;\r\n promise = searchByCriteriaAsync(\r\n {\r\n callerContext: context,\r\n queryResultSettings: input.queryResultSettings\r\n },\r\n searchCriteriaInput\r\n );\r\n } else if (input.searchText && context.requestContext.query && context.requestContext.query.recommendation) {\r\n const searchObject = JSON.parse(input.searchText);\r\n if (context.requestContext.query.productId) {\r\n searchProductId = Number(searchObject.ProductId);\r\n }\r\n if (Number.isNaN(searchProductId)) {\r\n throw new Error('Failed to cast search product id into a number.');\r\n } else if (\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- Existing code\r\n !searchObject.Recommendation\r\n ) {\r\n throw new Error('Failed to retrieve the Recommendation.');\r\n } else {\r\n searchCriteriaInput.SearchCondition = searchObject.SearchText;\r\n searchCriteriaInput.RecommendationListId = searchObject.Recommendation;\r\n if (searchProductId) {\r\n searchCriteriaInput.Ids = [searchProductId || defaultNumber];\r\n }\r\n promise = searchByCriteriaAsync(\r\n {\r\n callerContext: context,\r\n queryResultSettings: input.queryResultSettings\r\n },\r\n searchCriteriaInput\r\n );\r\n }\r\n } else if (input.searchText && context.requestContext.query?.discountIds) {\r\n const accountInformation = await getCustomer(new GetCustomerInput(context.requestContext.apiSettings), context);\r\n const discountIds = context.requestContext.query?.discountIds.split(',');\r\n\r\n const productPromotions = await getProductPromotionsAsync(\r\n {\r\n callerContext: context,\r\n queryResultSettings: input.queryResultSettings\r\n },\r\n discountIds ?? [],\r\n {\r\n HeaderContext: {\r\n ChannelId: context.requestContext.apiSettings.channelId,\r\n CustomerAccountNumber: accountInformation?.AccountNumber\r\n },\r\n LineContexts: [\r\n {\r\n CatalogId: input.catalogId\r\n }\r\n ]\r\n },\r\n new Date()\r\n );\r\n\r\n const productIds = productPromotions.map(p => p.ProductId ?? 0);\r\n searchCriteriaInput.Ids = productIds;\r\n searchCriteriaInput.CustomerAccountNumber = accountInformation.AccountNumber;\r\n\r\n promise = searchByCriteriaAsync(\r\n {\r\n callerContext: context,\r\n queryResultSettings: input.queryResultSettings\r\n },\r\n searchCriteriaInput\r\n );\r\n } else {\r\n throw new Error('[GetFullProductsForCollection]Search Page Detected, but no q= or productId= query parameter found');\r\n }\r\n\r\n let productSearchResults = await promise as ProductSearchResultExt[];\r\n\r\n // Reset non-active prices\r\n productSearchResults.forEach(x => {\r\n x.Price = 0;\r\n x.BasePrice = 0;\r\n x.MaxVariantPrice = 0;\r\n x.MinVariantPrice = 0;\r\n x.PrefetchedPrice = false;\r\n });\r\n\r\n if (context.requestContext.user.isAuthenticated) {\r\n try {\r\n const input = new CachedPriceForProductSearchResultInput(productSearchResults);\r\n const cached = await getCachedPriceForProductSearchResultDataAction(input, context);\r\n productSearchResults = cached;\r\n } catch (error) {\r\n // Do nothing, error is already logged in above function\r\n }\r\n }\r\n\r\n return returnProducts(productSearchResults, context, promise.metadata.count, channelInventoryConfiguration);\r\n}\r\n\r\nexport const actionDataAction = createObservableDataAction({\r\n id: '@msdyn365-commerce-modules/search-result-container/get-full-products-by-collection',\r\n action: action as IAction,\r\n input: createInput\r\n});\r\n\r\nexport default actionDataAction;\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport {\r\n CacheType,\r\n createObservableDataAction,\r\n IAction,\r\n IActionContext,\r\n IActionInput,\r\n IAny,\r\n ICommerceApiSettings,\r\n ICreateActionContext,\r\n IGeneric\r\n} from '@msdyn365-commerce/core';\r\nimport { SortColumn } from '@msdyn365-commerce/retail-proxy';\r\nimport { getSearchConfigurationAsync } from '@msdyn365-commerce/retail-proxy/dist/DataActions/StoreOperationsDataActions.g';\r\nimport { buildCacheKey } from '@msdyn365-commerce-modules/retail-actions';\r\n\r\n// TODO: import from commerce entities when available\r\n// eslint-disable-next-line @typescript-eslint/naming-convention -- Name change will require many modifications\r\ninterface SearchConfiguration {\r\n ProductSortColumns?: SortColumn[];\r\n}\r\n\r\n// eslint-disable-next-line @typescript-eslint/naming-convention -- Name change will require many modifications\r\nexport interface MappedSearchConfiguration {\r\n key: string;\r\n sortColumn: SortColumn;\r\n}\r\n\r\nexport const sortOptions = {\r\n sortByOptionRelevanceDesc: 'Ranking-Desc',\r\n sortByOptionRatingAsc: 'AverageRating-Asc',\r\n sortByOptionRatingDesc: 'AverageRating-Desc',\r\n sortByOptionNameAsc: 'Name-Asc',\r\n sortByOptionNameDesc: 'Name-Desc',\r\n sortByOptionPriceAsc: 'Price-Asc',\r\n sortByOptionPriceDesc: 'Price-Desc',\r\n sortByOptionBestSelling: 'BestSelling',\r\n sortByOptionNewScore: 'NewScore',\r\n sortByOptionTrendingScore: 'TrendingScore'\r\n};\r\n\r\n/**\r\n * ActionInput class for the get-mapped-search-configuration Data Action.\r\n */\r\nexport class MappedSearchInput implements IActionInput {\r\n private readonly apiSettings: ICommerceApiSettings;\r\n\r\n constructor(apiSettings: ICommerceApiSettings) {\r\n this.apiSettings = apiSettings;\r\n }\r\n\r\n public getCacheKey = () => buildCacheKey('MappedSearchInput', this.apiSettings);\r\n\r\n public getCacheObjectType = () => 'MappedSearchInput';\r\n\r\n public dataCacheType = (): CacheType => 'request';\r\n}\r\n\r\n/**\r\n * Get a mapped search configuration that is easy to use for sorting.\r\n * @param input\r\n * @param ctx\r\n */\r\nexport async function getMappedSearchConfiguration(input: MappedSearchInput, ctx: IActionContext): Promise {\r\n return getSearchConfigurationAsync({ callerContext: ctx }).then((searchConfiguration: SearchConfiguration) => {\r\n return (searchConfiguration.ProductSortColumns || [])\r\n .map((sortColumn: SortColumn) => {\r\n let key = '';\r\n if (sortColumn.ColumnName) {\r\n switch (sortColumn.ColumnName.toUpperCase()) {\r\n case 'NAME':\r\n key = sortColumn.IsDescending ? sortOptions.sortByOptionNameDesc : sortOptions.sortByOptionNameAsc;\r\n break;\r\n case 'PRICE':\r\n key = sortColumn.IsDescending ? sortOptions.sortByOptionPriceDesc : sortOptions.sortByOptionPriceAsc;\r\n break;\r\n case 'AVERAGERATING':\r\n key = sortColumn.IsDescending ? sortOptions.sortByOptionRatingDesc : sortOptions.sortByOptionRatingAsc;\r\n break;\r\n case 'RANKING':\r\n key = sortOptions.sortByOptionRelevanceDesc;\r\n break;\r\n case 'BESTSELLINGSCORE':\r\n key = sortOptions.sortByOptionBestSelling;\r\n break;\r\n case 'NEWSCORE':\r\n key = sortOptions.sortByOptionNewScore;\r\n break;\r\n case 'TRENDINGSCORE':\r\n key = sortOptions.sortByOptionTrendingScore;\r\n break;\r\n default:\r\n }\r\n } else {\r\n ctx.telemetry.warning('[get-mapped-search-configuration] unknown search option');\r\n }\r\n if (key) {\r\n return {\r\n key,\r\n sortColumn\r\n };\r\n }\r\n return undefined;\r\n })\r\n .filter(Boolean);\r\n });\r\n}\r\n\r\nexport const createInput = (inputData: ICreateActionContext>): IActionInput => {\r\n return new MappedSearchInput(inputData.requestContext.apiSettings);\r\n};\r\n\r\nexport const getMappedSearchConfigurationDataAction = createObservableDataAction({\r\n id: '@msdyn365-commerce-modules/search-result-container/get-mapped-search-configuration',\r\n action: >getMappedSearchConfiguration,\r\n input: createInput\r\n});\r\n\r\nexport default getMappedSearchConfigurationDataAction;\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { IProductRefinerHierarchy } from '@msdyn365-commerce/commerce-entities';\r\nimport { createObservableDataAction, IAction, IActionContext, IActionInput, ICreateActionContext } from '@msdyn365-commerce/core';\r\nimport { AsyncResult, ChannelInventoryConfiguration, ProductRefinerValue, ProductSearchCriteria } from '@msdyn365-commerce/retail-proxy';\r\nimport { getInventoryConfigurationAsync } from '@msdyn365-commerce/retail-proxy/dist/DataActions/StoreOperationsDataActions.g';\r\n\r\nimport { BaseCollectionInput, createBaseCollectionInput } from './base-collection-action';\r\nimport { getProductRefinerHierarchy } from './get-product-refiner-hierarchy';\r\nimport { getInventorySortableRefinerValue, ProductListInventoryFilteringOptions } from '.';\r\nimport { addOrUpdateZeroPriceRefiner, getAlcoholRefiners, getAllAttributeRefiners, shouldFilterAlcohol } from './refiner-utils';\r\n\r\n/**\r\n * Default Category/Product Id Values.\r\n */\r\nenum DefaultValues {\r\n defaultCategoryIdValue = 0,\r\n defaultProductIdValue = 0\r\n}\r\n\r\n/**\r\n * Refiners-by-Collection Input action.\r\n */\r\nexport class RefinersByCollectionInput extends BaseCollectionInput implements IActionInput {\r\n public getCacheObjectType = () => 'ProductRefiner';\r\n\r\n public dataCacheType = () => {\r\n return 'none';\r\n // @ts-ignore\r\n if (\r\n this.pageType !== 'Category' ||\r\n (this.refiners && this.refiners.length > 0) ||\r\n (this.queryResultSettings &&\r\n this.queryResultSettings.Sorting &&\r\n this.queryResultSettings.Sorting!.Columns &&\r\n this.queryResultSettings.Sorting!.Columns!.length > 0)\r\n ) {\r\n return 'request';\r\n }\r\n return 'application';\r\n };\r\n}\r\n\r\n/**\r\n * Create input method which creates an ActionInput for fetching list page refiners.\r\n * @param args\r\n */\r\nconst createInput = (args: ICreateActionContext): IActionInput => {\r\n return createBaseCollectionInput(args, RefinersByCollectionInput);\r\n};\r\n\r\n/**\r\n * Action method which fetches refiners for the given list page.\r\n * @param input\r\n * @param context\r\n */\r\nexport async function getRefinersForCollectionDataAction(input: RefinersByCollectionInput, context: IActionContext): Promise {\r\n let searchProductId;\r\n // Decouple refiners from input.refiners to avoid input.refiners being modified below\r\n let refiners: ProductRefinerValue[] = [...input.refiners] || [];\r\n\r\n let channelInventoryConfigurationPromise: AsyncResult;\r\n if (input.channelInventoryConfiguration) {\r\n channelInventoryConfigurationPromise = AsyncResult.resolve(input.channelInventoryConfiguration);\r\n } else {\r\n channelInventoryConfigurationPromise = getInventoryConfigurationAsync({ callerContext: context });\r\n }\r\n const channelInventoryConfiguration = await channelInventoryConfigurationPromise;\r\n\r\n // Replace InventoryProductAttribute with boolean refiner.\r\n // Because the value of InventoryProductAttribute is different from language to language since it's string type.\r\n // The cached old inventory refiner value may be hit when customer switch language which will lead to \"no products found\" issue.\r\n const inventoryRefiner = refiners.find(\r\n refiner => refiner.RefinerRecordId === channelInventoryConfiguration?.InventoryProductAttributeRecordId\r\n );\r\n if (inventoryRefiner) {\r\n refiners = refiners.filter(refiner => refiner.RefinerRecordId !== channelInventoryConfiguration?.InventoryProductAttributeRecordId);\r\n\r\n const isInStockRefiner =\r\n inventoryRefiner.LeftValueBoundString !== channelInventoryConfiguration?.InventoryOutOfStockAttributeValueText &&\r\n inventoryRefiner.RightValueBoundString !== channelInventoryConfiguration?.InventoryOutOfStockAttributeValueText;\r\n const inventoryRefinerValue = getInventorySortableRefinerValue(channelInventoryConfiguration, isInStockRefiner);\r\n\r\n const isInventoryRefinerValueExist = refiners.some(refiner => refiner.RefinerRecordId === inventoryRefinerValue?.RefinerRecordId);\r\n if (!isInventoryRefinerValueExist && inventoryRefinerValue) {\r\n refiners.push(inventoryRefinerValue);\r\n }\r\n }\r\n\r\n if (context.requestContext.app.config?.productListInventoryDisplay === ProductListInventoryFilteringOptions.HideOOS) {\r\n const isInStock = true;\r\n const inventoryInStockRefinerValue = getInventorySortableRefinerValue(channelInventoryConfiguration, isInStock);\r\n\r\n const isInventoryInStockRefinerValueExist = refiners.some(\r\n refiner => refiner.RefinerRecordId === inventoryInStockRefinerValue?.RefinerRecordId\r\n );\r\n if (!isInventoryInStockRefinerValueExist && inventoryInStockRefinerValue) {\r\n refiners.push(inventoryInStockRefinerValue);\r\n }\r\n }\r\n\r\n const alcoholFilter = shouldFilterAlcohol(context);\r\n const attributeRefiners = await getAllAttributeRefiners(context);\r\n\r\n // Either 'refiners' or 'defaultRefiners' will be used on 'isUpdateRefinerPanel'. But either way it should always\r\n // contain the zero price filter and alcohol refiner.\r\n refiners = addOrUpdateZeroPriceRefiner(context, refiners)\r\n .concat(alcoholFilter ? await getAlcoholRefiners(context) : [])\r\n .concat(attributeRefiners);\r\n const defaultRefiners = addOrUpdateZeroPriceRefiner(context)\r\n .concat(alcoholFilter ? await getAlcoholRefiners(context) : [])\r\n .concat(attributeRefiners);\r\n\r\n if (input.pageType === 'Category') {\r\n if (input.category) {\r\n input.refiners = input.isUpdateRefinerPanel ? refiners : defaultRefiners;\r\n return getProductRefinerHierarchy(\r\n {\r\n CategoryIds: [input.category || DefaultValues.defaultCategoryIdValue],\r\n Context: {\r\n ChannelId: input.apiSettings.channelId,\r\n CatalogId: input.catalogId\r\n },\r\n Refinement: input.isUpdateRefinerPanel ? refiners : defaultRefiners,\r\n SearchCondition: input.searchText\r\n },\r\n input.queryResultSettings,\r\n context\r\n );\r\n }\r\n throw new Error('[GetRefinersForCollection]Category Page Detected, but no global categoryId found');\r\n } else {\r\n if (input.searchText && context.requestContext.query && context.requestContext.query.q && !context.requestContext.query.recommendation) {\r\n input.refiners = input.isUpdateRefinerPanel ? refiners : defaultRefiners;\r\n return getProductRefinerHierarchy(\r\n {\r\n SearchCondition: input.searchText,\r\n Context: {\r\n ChannelId: input.apiSettings.channelId,\r\n CatalogId: input.catalogId\r\n },\r\n Refinement: input.isUpdateRefinerPanel ? refiners : defaultRefiners\r\n },\r\n input.queryResultSettings,\r\n context\r\n );\r\n }\r\n if (input.searchText && context.requestContext.query && context.requestContext.query.recommendation) {\r\n const searchObject = JSON.parse(input.searchText);\r\n if (context.requestContext.query.productId) {\r\n searchProductId = Number(searchObject.ProductId);\r\n }\r\n if (Number.isNaN(searchProductId)) {\r\n throw new Error('Failed to cast search product id into a number.');\r\n } else if (!searchObject.Recommendation) {\r\n throw new Error('Failed to retrieve the Recommendation.');\r\n } else {\r\n const searchCriteriaInput: ProductSearchCriteria = {};\r\n input.refiners = input.isUpdateRefinerPanel ? refiners : defaultRefiners;\r\n searchCriteriaInput.Context = {\r\n ChannelId: input.apiSettings.channelId,\r\n CatalogId: input.catalogId\r\n };\r\n searchCriteriaInput.SearchCondition = searchObject.SearchText;\r\n searchCriteriaInput.Refinement = input.isUpdateRefinerPanel ? refiners : defaultRefiners;\r\n searchCriteriaInput.RecommendationListId = searchObject.Recommendation;\r\n if (searchProductId) {\r\n searchCriteriaInput.Ids = [searchProductId || DefaultValues.defaultProductIdValue];\r\n }\r\n return getProductRefinerHierarchy(searchCriteriaInput, input.queryResultSettings, context);\r\n }\r\n } else {\r\n throw new Error('[GetFullProductsForCollection]Search Page Detected, but no q= or productId= query parameter found');\r\n }\r\n }\r\n}\r\n\r\nexport const actionDataAction = createObservableDataAction({\r\n id: '@msdyn365-commerce-modules/search-result-container/get-refiners-for-collection',\r\n action: >getRefinersForCollectionDataAction,\r\n input: createInput\r\n});\r\n\r\nexport default actionDataAction;\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { IProductRefinerHierarchy } from '@msdyn365-commerce/commerce-entities';\r\nimport { CacheType, createObservableDataAction, IAction, IActionContext, IActionInput } from '@msdyn365-commerce/core';\r\nimport { buildCacheKey } from '@msdyn365-commerce-modules/retail-actions';\r\n\r\nimport {\r\n AttributeDataType,\r\n ChannelInventoryConfiguration,\r\n ProductRefinerSource,\r\n ProductRefinerValue\r\n} from '@msdyn365-commerce/retail-proxy';\r\nimport { BaseCollectionInput } from './base-collection-action';\r\nimport { getProductRefinerHierarchy } from './get-product-refiner-hierarchy';\r\n\r\n/**\r\n * Returns inventory in stock sortable refiner value.\r\n * @param channelInventoryConfiguration - The channelInventoryConfiguration.\r\n * @param isInStock - The flag indicating whether is getting in-stock refiner or out-of-stock refiner.\r\n * @returns Refiners.\r\n */\r\nexport const getInventorySortableRefinerValue = (\r\n channelInventoryConfiguration: ChannelInventoryConfiguration,\r\n isInStock: boolean\r\n): ProductRefinerValue | undefined => {\r\n if (channelInventoryConfiguration && channelInventoryConfiguration.ProductAvailabilitySortableAttributeRecordId) {\r\n return {\r\n RefinerRecordId: channelInventoryConfiguration.ProductAvailabilitySortableAttributeRecordId,\r\n DataTypeValue: AttributeDataType.TrueFalse,\r\n LeftValueBoundString: isInStock ? 'true' : 'false',\r\n RightValueBoundString: isInStock ? 'true' : 'false',\r\n UnitText: '',\r\n RowNumber: 0,\r\n Count: 0,\r\n ExtensionProperties: [],\r\n RefinerSourceValue: ProductRefinerSource.Attribute\r\n };\r\n }\r\n return undefined;\r\n};\r\n\r\n/**\r\n * InventoryInStockRefinerValue Input action.\r\n * @remark The get-inventory-refiners data action is obsoleted. Please use getInventorySortableRefinerValue instead.\r\n */\r\nexport class InventoryInStockRefinerValueInput extends BaseCollectionInput implements IActionInput {\r\n public inventoryProductAttributeRecordId: number;\r\n\r\n public constructor(input: BaseCollectionInput, inventoryProductAttributeRecordId: number = 0) {\r\n super(\r\n input.pageType,\r\n input.apiSettings,\r\n {\r\n count: true\r\n },\r\n\r\n // Parameter - refiners\r\n [],\r\n\r\n // Parameter - category\r\n undefined,\r\n\r\n // Parameter - searchText\r\n '',\r\n\r\n // Parameter - includeAttributes\r\n false,\r\n\r\n // Parameter - isUpdateRefinerPanel\r\n false,\r\n\r\n // Parameter - locale\r\n undefined,\r\n input.catalogId,\r\n input.channelInventoryConfiguration,\r\n input.inventoryRefiner\r\n );\r\n\r\n this.inventoryProductAttributeRecordId =\r\n inventoryProductAttributeRecordId || input.channelInventoryConfiguration?.InventoryProductAttributeRecordId || 0;\r\n }\r\n\r\n /**\r\n * GetCacheKey.\r\n * @returns - Returns string.\r\n */\r\n public getCacheKey = (): string => buildCacheKey('RefinerList', this.apiSettings);\r\n\r\n /**\r\n * GetCacheObjectType.\r\n * @returns - Returns string.\r\n */\r\n public getCacheObjectType = (): string => 'RefinerList';\r\n\r\n /**\r\n * DataCacheType.\r\n * @returns - CacheType string.\r\n */\r\n public dataCacheType = (): CacheType => 'application';\r\n}\r\n\r\n/**\r\n * Action method returns inventory in stock refiners.\r\n * @param input - InventoryInStockRefinerValueInput.\r\n * @param context - IActionContext.\r\n * @returns - Promise.\r\n * @remark The get-inventory-refiners data action is obsoleted. Please use getInventorySortableRefinerValue instead.\r\n */\r\nasync function action(input: InventoryInStockRefinerValueInput, context: IActionContext): Promise {\r\n const refiners = await getProductRefinerHierarchy(\r\n {\r\n Context: {\r\n ChannelId: input.apiSettings.channelId,\r\n CatalogId: input.catalogId\r\n }\r\n },\r\n input.queryResultSettings,\r\n context\r\n );\r\n\r\n // InventoryProductAttributeRecordId may be 0, and recId of default refiner Category/Price/Rating is always 0 by design. In this case, we should not return refiner\r\n // Why recId of default refiner Category/Price/Rating is 0: see GetChannelProductRefiners.sql\r\n return (\r\n (input.channelInventoryConfiguration?.InventoryProductAttributeRecordId !== 0 &&\r\n refiners.find(refiner => refiner.RecordId === input.channelInventoryConfiguration?.InventoryProductAttributeRecordId)) ||\r\n // keep legacy logic to avoid break existing customers usage from this file\r\n (input.inventoryProductAttributeRecordId !== 0 &&\r\n refiners.find(refiner => refiner.RecordId === input.inventoryProductAttributeRecordId)) ||\r\n null\r\n );\r\n}\r\n\r\n/**\r\n * Action.\r\n * @param id - Id.\r\n * @param action - Action.\r\n * @returns - Results.\r\n * @remark The get-inventory-refiners data action is obsoleted. Please use getInventorySortableRefinerValue instead.\r\n */\r\nexport const actionDataAction = createObservableDataAction({\r\n id: '@msdyn365-commerce-modules/search-result-container/get-inventory-refiners',\r\n action: action as IAction\r\n});\r\n\r\nexport default actionDataAction;\r\n","import { IActionContext } from '@msdyn365-commerce/core';\r\nimport { AttributeDataType, CustomerAttribute, ProductRefinerSource, ProductRefinerValue, ProductSearchCriteria } from '@msdyn365-commerce/retail-proxy';\r\n// @ts-ignore\r\nimport { getCustomer, GetCustomerInput } from '@msdyn365-commerce-modules/retail-actions';\r\nimport getOrganizationCustomer, { GetOrganizationCustomerInput } from '../../../actions/get-organization-customer';\r\n\r\n// Pre populated with ids from STAGE for local development\r\nconst AlcoholGroupAttributeId = 5637155076;\r\n\r\nfunction isGodmodeEnabled(context: IActionContext): boolean {\r\n const godmode = context.requestContext.url.requestUrl.searchParams.get('godmode')?.toLowerCase();\r\n\r\n return godmode === '1' || godmode === 'true';\r\n}\r\n\r\nexport function shouldFilterAlcohol(context: IActionContext): boolean {\r\n const doAlcoholFiltering = context.requestContext.url.requestUrl.searchParams.get('alcohol')?.toLowerCase() !== 'false';\r\n const alcoholRefinerRecordId = Number(context.requestContext.app.config?.alcoholRefinerRecordId);\r\n\r\n return doAlcoholFiltering && !isNaN(alcoholRefinerRecordId) && alcoholRefinerRecordId > 0;\r\n}\r\n\r\nexport async function getAlcoholRefiners(context: IActionContext): Promise {\r\n let alcoholGroupAttributeId = Number(context.requestContext.app.config?.alcoholRefinerRecordId);\r\n\r\n if (isNaN(alcoholGroupAttributeId) || alcoholGroupAttributeId === 0) {\r\n alcoholGroupAttributeId = AlcoholGroupAttributeId;\r\n }\r\n\r\n const result: ProductRefinerValue[] = [];\r\n const alcoholRefiner: ProductRefinerValue = {\r\n DataTypeValue: 5,\r\n LeftValueBoundString: '0',\r\n RefinerRecordId: alcoholGroupAttributeId,\r\n RefinerSourceValue: 1,\r\n RightValueBoundString: '0',\r\n UnitText: ''\r\n };\r\n\r\n result.push(alcoholRefiner);\r\n\r\n try {\r\n let alcoholLicenseValue = 0;\r\n\r\n if (context.requestContext.user.isAuthenticated) {\r\n // Get Customer attributes\r\n // const customer = await getCustomer(new GetCustomerInput(context.requestContext.apiSettings, context.requestContext.user.customerAccountNumber), context);\r\n const customer = await getOrganizationCustomer(new GetOrganizationCustomerInput(context.requestContext.apiSettings, context.requestContext.user.customerAccountNumber!), context);\r\n const alcoholLicense = Number(customer.Attributes?.find(x => x.RecordId === alcoholGroupAttributeId)?.AttributeValue?.StringValue);\r\n\r\n if (isNaN(alcoholLicense)) {\r\n // Throw NaN error\r\n console.warn('Alcohol license value is missing or not a number.');\r\n } else {\r\n alcoholLicenseValue = alcoholLicense;\r\n }\r\n } else {\r\n // If user is not logged in show all products\r\n alcoholLicenseValue = 3;\r\n }\r\n\r\n // TODO: Verify we can do ranges like this on text attributes\r\n // If we can do range on text attributes use this:\r\n //alcoholRefiner.RightValueBoundString = alcoholLicense?.AttributeValue?.StringValue ?? '0';\r\n\r\n // Add a refiner for each alcohol group\r\n Array(alcoholLicenseValue).fill(0).forEach((_, index) => {\r\n result.push({\r\n ...alcoholRefiner,\r\n LeftValueBoundString: (index + 1).toString(),\r\n RightValueBoundString: (index + 1).toString()\r\n });\r\n });\r\n } catch (error) {\r\n console.warn('Failed to get customer attributes for alcohol license or parse value of attribute. No alcohol license applied to search.', error);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport async function addAlcoholRefiner(context: IActionContext, searchCriteriaInput: ProductSearchCriteria): Promise {\r\n let alcoholGroupAttributeId = Number(context.requestContext.app.config?.alcoholRefinerRecordId);\r\n\r\n if (isNaN(alcoholGroupAttributeId) || alcoholGroupAttributeId === 0) {\r\n alcoholGroupAttributeId = AlcoholGroupAttributeId;\r\n }\r\n\r\n if (searchCriteriaInput.Refinement!.some(x => x.RefinerRecordId === alcoholGroupAttributeId)) {\r\n // Remove existing, shouldn't be here\r\n searchCriteriaInput.Refinement = searchCriteriaInput.Refinement!.filter(x => x.RefinerRecordId !== alcoholGroupAttributeId);\r\n }\r\n\r\n const refiners = await getAlcoholRefiners(context);\r\n\r\n searchCriteriaInput.Refinement = searchCriteriaInput.Refinement!.concat(refiners);\r\n\r\n return Promise.resolve();\r\n}\r\n\r\nexport function addOrUpdateZeroPriceRefiner(context: IActionContext, refiners?: ProductRefinerValue[]): ProductRefinerValue[] {\r\n // Check criteria for allowing user to see zero price products. Example:\r\n // - Has ?godmode=true in url\r\n const allowZeroPriceProducts = isGodmodeEnabled(context);\r\n\r\n if (!allowZeroPriceProducts) {\r\n const result = refiners ? [...refiners] : [];\r\n\r\n // Make sure we don't show zero price products\r\n const priceRefiner = result.find(x => x.RefinerRecordId === 0);\r\n\r\n if (priceRefiner) {\r\n // There is a price refiner, make sure it has a min value of 0.01 or more\r\n if (!priceRefiner.LeftValueBoundString || Number(priceRefiner.LeftValueBoundString) < 0.01) {\r\n priceRefiner.LeftValueBoundString = '0.01';\r\n }\r\n } else {\r\n // No price refiner, add one\r\n result.push({\r\n '@odata.type': '#Microsoft.Dynamics.Commerce.Runtime.DataModel.ProductRefinerValue',\r\n Count: 0,\r\n DataTypeValue: 1,\r\n LeftValueBoundString: '0.01',\r\n ExtensionProperties: [],\r\n RefinerRecordId: 0,\r\n RefinerSourceValue: 3,\r\n RightValueBoundString: '1000000000',\r\n RowNumber: 0,\r\n UnitText: context.requestContext.channel?.Currency\r\n } as any);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n return refiners || [];\r\n}\r\n\r\nexport async function getAttributeRefiners(context: IActionContext, customerAttributes: CustomerAttribute[] | undefined, attributeRecordId: number, friendlyName?: string): Promise {\r\n const result: ProductRefinerValue[] = [];\r\n const refiner: ProductRefinerValue = {\r\n DataTypeValue: 5,\r\n LeftValueBoundString: '0',\r\n RefinerRecordId: attributeRecordId,\r\n RefinerSourceValue: 1,\r\n RightValueBoundString: '0',\r\n UnitText: ''\r\n };\r\n\r\n result.push(refiner);\r\n\r\n try {\r\n let attributeValue = 0;\r\n\r\n if (context.requestContext.user.isAuthenticated) {\r\n const attribute = Number(customerAttributes?.find(x => x.RecordId === attributeRecordId)?.AttributeValue?.StringValue);\r\n\r\n if (isNaN(attribute)) {\r\n // Throw NaN error\r\n if (friendlyName) {\r\n console.warn(`${friendlyName} attribute value is missing or not a number.`);\r\n } else {\r\n console.warn(`Attribute with record id ${attributeRecordId} is missing a value or not a number.`);\r\n }\r\n } else {\r\n attributeValue = attribute;\r\n }\r\n } else {\r\n // If user is not logged in show all products\r\n attributeValue = 1;\r\n }\r\n\r\n if (attributeValue !== 0) {\r\n result.push({\r\n ...refiner,\r\n LeftValueBoundString: attributeValue.toString(),\r\n RightValueBoundString: attributeValue.toString()\r\n });\r\n }\r\n } catch (error) {\r\n if (friendlyName) {\r\n console.warn(`Failed to get ${friendlyName} customer attribute or parse value of attribute. No filter applied to search.`, error);\r\n } else {\r\n console.warn(`Failed to get customer attribute (record id: ${attributeRecordId}) or parse value of attribute. No filter applied to search.`, error);\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport async function getForsvaretRefiner(context: IActionContext, customerAttributes: CustomerAttribute[] | undefined): Promise {\r\n const forsvaretAttributeId = context.requestContext.app.config?.forsvaretAttributeRecordId;\r\n\r\n if (!forsvaretAttributeId || !context.requestContext.user.isAuthenticated) {\r\n return;\r\n }\r\n\r\n try {\r\n const attribute = customerAttributes?.find(x => x.RecordId === Number(forsvaretAttributeId))?.AttributeValue?.IntegerValue;\r\n\r\n if (!attribute || isNaN(attribute) || attribute === 0) {\r\n return;\r\n }\r\n\r\n return {\r\n DataTypeValue: AttributeDataType.Integer,\r\n LeftValueBoundString: attribute.toString(),\r\n RefinerRecordId: Number(forsvaretAttributeId),\r\n RefinerSourceValue: ProductRefinerSource.Attribute,\r\n RightValueBoundString: attribute.toString(),\r\n UnitText: ''\r\n };\r\n } catch (error) {\r\n console.error('Failed to get forsvaret attribute', error);\r\n return;\r\n }\r\n}\r\n\r\nexport async function getSvalbardRefiner(context: IActionContext, customerAttributes: CustomerAttribute[] | undefined): Promise {\r\n if (!context.requestContext.user.isAuthenticated) {\r\n return;\r\n }\r\n\r\n const svalbardAttributeId = context.requestContext.app.config?.svalbardAttributeRecordId;\r\n const blockedSvalbardAttributeId = context.requestContext.app.config?.blockedSvalbardAttributeRecordId;\r\n\r\n // Both config needs to be set to something\r\n if (!svalbardAttributeId || !blockedSvalbardAttributeId) {\r\n return;\r\n }\r\n\r\n // Both config needs to be numbers. This allows users to prepend values with a character to temporarily disable the refiner\r\n if (isNaN(svalbardAttributeId) || isNaN(blockedSvalbardAttributeId)) {\r\n return;\r\n }\r\n\r\n try {\r\n const attribute = customerAttributes?.find(x => x.RecordId === Number(svalbardAttributeId))?.AttributeValue?.IntegerValue;\r\n\r\n // Check if attribute is set, is a number and above 0\r\n if (!attribute || isNaN(attribute) || attribute <= 0) {\r\n return;\r\n }\r\n\r\n // Add refiner so that only products that isn't blocked for svalbard is shown since customer attribute is set to 1 or more\r\n return {\r\n DataTypeValue: AttributeDataType.Integer,\r\n LeftValueBoundString: '0',\r\n RefinerRecordId: Number(blockedSvalbardAttributeId),\r\n RefinerSourceValue: ProductRefinerSource.Attribute,\r\n RightValueBoundString: '0',\r\n UnitText: ''\r\n };\r\n } catch (error) {\r\n console.error('Failed to get svalbard attribute(s)', error);\r\n return;\r\n }\r\n}\r\n\r\nexport async function addAttributeRefiner(context: IActionContext, customerAttributes: CustomerAttribute[] | undefined, searchCriteriaInput: ProductSearchCriteria, attributeRecordId: number): Promise {\r\n if (searchCriteriaInput.Refinement!.some(x => x.RefinerRecordId === attributeRecordId)) {\r\n // Remove existing, shouldn't be here\r\n searchCriteriaInput.Refinement = searchCriteriaInput.Refinement!.filter(x => x.RefinerRecordId !== attributeRecordId);\r\n }\r\n\r\n const refiners = await getAttributeRefiners(context, customerAttributes, attributeRecordId);\r\n\r\n searchCriteriaInput.Refinement = searchCriteriaInput.Refinement!.concat(refiners);\r\n}\r\n\r\nexport async function addAttributeRefinerKeepExisting(context: IActionContext, customerAttributes: CustomerAttribute[] | undefined, searchCriteriaInput: ProductSearchCriteria, attributeRecordId: number): Promise {\r\n if (searchCriteriaInput.Refinement!.some(x => x.RefinerRecordId === attributeRecordId)) {\r\n return;\r\n }\r\n\r\n const refiners = await getAttributeRefiners(context, customerAttributes, attributeRecordId);\r\n\r\n searchCriteriaInput.Refinement = searchCriteriaInput.Refinement!.concat(refiners);\r\n}\r\n\r\nexport async function addAllAttributeRefiners(context: IActionContext, searchCriteriaInput: ProductSearchCriteria): Promise {\r\n const godmode = isGodmodeEnabled(context);\r\n\r\n if (godmode) {\r\n return;\r\n }\r\n\r\n let customerAttributes: CustomerAttribute[] | undefined = [];\r\n\r\n if (context.requestContext.user.isAuthenticated) {\r\n const { apiSettings, user: { customerAccountNumber } } = context.requestContext;\r\n const customer = await getOrganizationCustomer(new GetOrganizationCustomerInput(apiSettings, customerAccountNumber!), context);\r\n customerAttributes = customer.Attributes;\r\n }\r\n\r\n const attributeRecordIds: string[] = [\r\n context.requestContext.app.config?.tobaccoRefinerRecordId,\r\n context.requestContext.app.config?.cocacolaRefinerRecordId,\r\n context.requestContext.app.config?.bamaRefinerRecordId,\r\n context.requestContext.app.config?.dutyFreeSugarRefinerRecordId,\r\n context.requestContext.app.config?.norturaRefinerRecordId\r\n ];\r\n\r\n for (const attributeRecordId of attributeRecordIds) {\r\n const id = Number(attributeRecordId);\r\n\r\n // Make sure it's a number and above 0\r\n if (!isNaN(id) && id > 0) {\r\n await addAttributeRefiner(context, customerAttributes, searchCriteriaInput, id);\r\n }\r\n }\r\n\r\n const transitRefiner = Number(context.requestContext.app.config?.transitRefinerRecordId);\r\n\r\n if (!isNaN(transitRefiner) && transitRefiner > 0) {\r\n await addAttributeRefinerKeepExisting(context, customerAttributes, searchCriteriaInput, transitRefiner);\r\n }\r\n\r\n const forsvaretRefiner = await getForsvaretRefiner(context, customerAttributes);\r\n\r\n if (forsvaretRefiner) {\r\n searchCriteriaInput.Refinement!.push(forsvaretRefiner);\r\n }\r\n\r\n const svalbardRefiner = await getSvalbardRefiner(context, customerAttributes);\r\n\r\n if (svalbardRefiner) {\r\n searchCriteriaInput.Refinement!.push(svalbardRefiner);\r\n }\r\n}\r\n\r\nexport async function getAllAttributeRefiners(context: IActionContext) {\r\n const godmode = isGodmodeEnabled(context);\r\n\r\n if (godmode) {\r\n return [];\r\n }\r\n\r\n let customerAttributes: CustomerAttribute[] | undefined = [];\r\n\r\n if (context.requestContext.user.isAuthenticated) {\r\n const { apiSettings, user: { customerAccountNumber } } = context.requestContext;\r\n const customer = await getOrganizationCustomer(new GetOrganizationCustomerInput(apiSettings, customerAccountNumber!), context);\r\n customerAttributes = customer.Attributes;\r\n }\r\n\r\n const attributeRecordIds: string[] = [\r\n context.requestContext.app.config?.transitRefinerRecordId,\r\n context.requestContext.app.config?.tobaccoRefinerRecordId,\r\n context.requestContext.app.config?.cocacolaRefinerRecordId,\r\n context.requestContext.app.config?.bamaRefinerRecordId,\r\n context.requestContext.app.config?.dutyFreeSugarRefinerRecordId,\r\n context.requestContext.app.config?.norturaRefinerRecordId\r\n ];\r\n\r\n const result: ProductRefinerValue[] = [];\r\n\r\n for (const attributeRecordId of attributeRecordIds) {\r\n const id = Number(attributeRecordId);\r\n\r\n // Make sure it's a number and above 0\r\n if (!isNaN(id) && id > 0) {\r\n const refiners = await getAttributeRefiners(context, customerAttributes, id);\r\n result.push(...refiners);\r\n }\r\n }\r\n\r\n const forsvaretRefiner = await getForsvaretRefiner(context, customerAttributes);\r\n\r\n if (forsvaretRefiner) {\r\n result.push(forsvaretRefiner);\r\n }\r\n\r\n const svalbardRefiner = await getSvalbardRefiner(context, customerAttributes);\r\n\r\n if (svalbardRefiner) {\r\n result.push(svalbardRefiner);\r\n }\r\n\r\n return result;\r\n}","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport MsDyn365, { IRequestContext } from '@msdyn365-commerce/core';\r\nimport { ProductRefinerValue, SortColumn } from '@msdyn365-commerce/retail-proxy';\r\n\r\n/**\r\n * Refiner Compression:\r\n * Refiners contains a non-trivial amount of data that is required to successfully make\r\n * a refiner-based API call. To allow for deep-linking of refiners in the URL, refiner data\r\n * must be compressed so that URL max length is not exceeded. Refiners will be compressed into\r\n * the following array style index-based format:\r\n * [DataTypeValue, LeftValueBoundString, RefinerRecordId, RefinerSourceValue, RightValueBoundString, UnitText].\r\n */\r\nconst compressedRefinerKeys = [\r\n 'DataTypeValue',\r\n 'LeftValueBoundString',\r\n 'RefinerRecordId',\r\n 'RefinerSourceValue',\r\n 'RightValueBoundString',\r\n 'UnitText',\r\n // Added RowNumber to identify if custom range integer or API values option is selected\r\n 'RowNumber'\r\n];\r\n\r\n/**\r\n * Hydrates compressed refiner data from URL.\r\n * @param fullUrl The full URL of the page.\r\n * @param requestContext\r\n */\r\nexport const hydrateRefinersFromUrl = (requestContext: IRequestContext): ProductRefinerValue[] => {\r\n const compressedRefinerArray = parseQueryParam<(string | number)[][]>('refiners', requestContext);\r\n if (!compressedRefinerArray || compressedRefinerArray.length === 0) {\r\n return [];\r\n }\r\n\r\n return compressedRefinerArray\r\n .map(compressedRefiner => {\r\n try {\r\n const parsedRefiner: ProductRefinerValue = {};\r\n compressedRefinerKeys.forEach((refinerKey, index) => {\r\n parsedRefiner[refinerKey] = compressedRefiner[index];\r\n });\r\n return parsedRefiner;\r\n } catch {\r\n return undefined;\r\n }\r\n })\r\n .filter(Boolean);\r\n};\r\n\r\n/**\r\n * Compressed a list of refiners for use in URLs.\r\n * @param refiners The uncompressed refiners.\r\n */\r\nexport const compressRefiners = (refiners: ProductRefinerValue[]) => {\r\n const compressedRefiners: (string | number)[][] = [];\r\n\r\n refiners.forEach(refiner => {\r\n const compressedRefiner: (string | number)[] = [];\r\n compressedRefinerKeys.forEach(refinerKey => {\r\n compressedRefiner.push(refiner[refinerKey]);\r\n });\r\n compressedRefiners.push(compressedRefiner);\r\n });\r\n\r\n return compressedRefiners;\r\n};\r\n\r\n/**\r\n * Method which creates a URL contiaining serialized active refiners.\r\n * @param fullUrl The Current URL of the page.\r\n * @param refiners The refiners which should be added to the URL.\r\n * @param sortingColumns\r\n * @param skipCount\r\n */\r\nexport const buildListPageUrl = (fullUrl: URL, refiners?: ProductRefinerValue[], sortingColumns?: SortColumn[], skipCount?: number) => {\r\n // Refiner Change flow\r\n if (refiners !== undefined) {\r\n if (refiners.length === 0) {\r\n fullUrl.searchParams.delete('refiners');\r\n } else {\r\n const sortedRefiners = refiners.sort((first, second) =>\r\n first.RefinerRecordId && second.RefinerRecordId && first.RefinerRecordId > second.RefinerRecordId ? 1 : -1\r\n );\r\n fullUrl.searchParams.set('refiners', JSON.stringify(compressRefiners(sortedRefiners)));\r\n }\r\n\r\n // Adding or removing a refiner means we want to always load page 1\r\n fullUrl.searchParams.delete('skip');\r\n return fullUrl.href;\r\n }\r\n\r\n if (sortingColumns !== undefined) {\r\n if (sortingColumns.length === 0) {\r\n fullUrl.searchParams.delete('sorting');\r\n } else {\r\n fullUrl.searchParams.set('sorting', JSON.stringify(sortingColumns));\r\n }\r\n\r\n // Changing the sort means always load page 1\r\n fullUrl.searchParams.delete('skip');\r\n return fullUrl.href;\r\n }\r\n\r\n if (skipCount) {\r\n fullUrl.searchParams.set('skip', skipCount.toString());\r\n }\r\n\r\n return fullUrl.href;\r\n};\r\n\r\n/**\r\n * Parses a query param from the query object of the request context.\r\n * @param key The query parameter key.\r\n * @param requestContext The request context.\r\n */\r\nexport const parseQueryParam = (key: string, requestContext: IRequestContext): T | null => {\r\n if (requestContext.query && requestContext.query[key]) {\r\n // NOTE: Query seems to already be decoded\r\n //return JSON.parse(decodeURIComponent(requestContext.query[key]));\r\n\r\n return JSON.parse(requestContext.query[key]);\r\n }\r\n return null;\r\n};\r\n\r\n/**\r\n * Gets the current URL of the page from the request context.\r\n * @param requestContext The request context.\r\n */\r\nexport const getCurrentUrl = (requestContext: IRequestContext): URL => {\r\n if (MsDyn365.isBrowser) {\r\n return new URL(window.location.href);\r\n }\r\n\r\n // NOTE: Typing on requestURL is incorrect\r\n if (requestContext.url.requestUrl.href) {\r\n return new URL(requestContext.url.requestUrl.href);\r\n }\r\n return new URL((requestContext.url.requestUrl));\r\n};\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { IProductRefinerHierarchy } from '@msdyn365-commerce/commerce-entities';\r\nimport { ProductRefinerValue } from '@msdyn365-commerce/retail-proxy';\r\nimport { getPayloadObject, getTelemetryAttributes, IPayLoad } from '@msdyn365-commerce-modules/utilities';\r\nimport classnames from 'classnames';\r\nimport { computed } from 'mobx';\r\nimport { observer } from 'mobx-react';\r\nimport * as React from 'react';\r\n\r\nimport { ProductListInventoryFilteringOptions } from '../actions';\r\nimport { IChoiceSummaryProps } from './choice-summary.props';\r\nimport { isBoolean, isMatchingRefinementCriterion, isRangeType } from './utilities';\r\n\r\ninterface IRefinerMap {\r\n key: string,\r\n parent?:string\r\n value: ProductRefinerValue;\r\n}\r\ninterface IRefinerKey {\r\n key: string;\r\n parent?:string\r\n}\r\n\r\n/**\r\n * ChoiceSummary component.\r\n */\r\n@observer\r\nexport default class ChoiceSummary extends React.PureComponent {\r\n private readonly closeButtonGlyph: string = 'msi-close-btn';\r\n\r\n private readonly payLoad: IPayLoad;\r\n\r\n @computed get selectedRefinersMap(): IRefinerMap[] {\r\n let { selectedChoices } = this.props;\r\n const { channelInventoryConfigurationId, refinerHierarchy } = this.props;\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- app configs are of generic type\r\n if (this.props.context?.app.config.productListInventoryDisplay === ProductListInventoryFilteringOptions.HideOOS) {\r\n selectedChoices = selectedChoices.filter(choice => {\r\n const parent = refinerHierarchy?.find(\r\n (hierarchy: IProductRefinerHierarchy) =>\r\n !!hierarchy.Values.find((value: ProductRefinerValue) => isMatchingRefinementCriterion(value, choice))\r\n );\r\n return parent && parent.RecordId !== channelInventoryConfigurationId;\r\n });\r\n }\r\n return selectedChoices.map((selectedRefiner: ProductRefinerValue, index) => {\r\n const RefinerValue=this._getKeyForRefinerValue(selectedRefiner, index.toString());\r\n return {\r\n key: RefinerValue.key,\r\n parent:RefinerValue.parent,\r\n value: selectedRefiner\r\n } as IRefinerMap;\r\n });\r\n }\r\n\r\n constructor(props: Readonly) {\r\n super(props);\r\n this.payLoad = getPayloadObject('click', this.props.telemetryContent!, '');\r\n }\r\n\r\n public render(): JSX.Element {\r\n const { clearAllText, label, classNames, choiceAriaLabel, closeAriaLabel,yesLabel,noLabel } = this.props;\r\n const items = this.selectedRefinersMap;\r\n this.payLoad.contentAction.etext = clearAllText;\r\n const clearAllAttributes = getTelemetryAttributes(this.props.telemetryContent!, this.payLoad);\r\n return (\r\n
\r\n {items.length > 0 && label && {label}}\r\n
    \r\n {items.map((item: IRefinerMap) => {\r\n this.payLoad.contentAction.etext = item.key;\r\n const attribute = getTelemetryAttributes(this.props.telemetryContent!, this.payLoad);\r\n let LeftValueBoundString = item.value.LeftValueBoundString;\r\n if (item.value && isBoolean(item.value.DataTypeValue)) {\r\n LeftValueBoundString = LeftValueBoundString === '1' ? yesLabel : noLabel;\r\n } else if (Number(this.props.transitRefinerRecordId) === item.value.RefinerRecordId) {\r\n LeftValueBoundString = LeftValueBoundString === '1' ? yesLabel : noLabel;\r\n } else if (item.parent === 'Sperret for Svalbard') {\r\n LeftValueBoundString = LeftValueBoundString === '1' ? yesLabel : noLabel;\r\n }\r\n return (\r\n
  • \r\n \r\n {item?.parent && {item.parent}:}\r\n {LeftValueBoundString && item.value.LeftValueBoundLocalizedString === ''\r\n ? LeftValueBoundString\r\n : (item.value.LeftValueBoundLocalizedString ||\r\n item.value.LeftValueBoundLocalizedString === undefined) &&\r\n item.value.RefinerRecordId === 0\r\n ? item.key\r\n : LeftValueBoundString}\r\n \r\n \r\n
  • \r\n );\r\n })}\r\n
\r\n {items.length > 0 && clearAllText && (\r\n \r\n {clearAllText}\r\n \r\n )}\r\n
\r\n );\r\n }\r\n\r\n private _getKeyForRefinerValue(productRefinerValue: ProductRefinerValue, index: string): IRefinerKey {\r\n const { choiceFormat, choiceRangeValueFormat, refinerHierarchy, telemetry, refinerValues } = this.props;\r\n const overallFormat = choiceFormat || '{1}';\r\n const rangeFormat = choiceRangeValueFormat;\r\n let refinerName = '';\r\n if (refinerHierarchy && refinerHierarchy.find) {\r\n const parent = refinerHierarchy.find(\r\n (hierarchy: IProductRefinerHierarchy) =>\r\n !!hierarchy.Values.find((value: ProductRefinerValue) => isMatchingRefinementCriterion(value, productRefinerValue))\r\n );\r\n\r\n if (!parent) {\r\n telemetry.warning('[choice-summary] could not find parent of selected refiner value');\r\n } else {\r\n refinerName = parent.KeyName || '';\r\n }\r\n }\r\n let refinerValueName: string;\r\n if (isRangeType(productRefinerValue.DataTypeValue)) {\r\n refinerValueName = rangeFormat\r\n .replace('{0}', this._formatPrice(productRefinerValue.LeftValueBoundString, productRefinerValue.UnitText))\r\n .replace('{1}', this._formatPrice(productRefinerValue.RightValueBoundString, productRefinerValue.UnitText));\r\n } else if (productRefinerValue.RefinerRecordId === 0) {\r\n const filterValue = refinerValues?.Values.find(\r\n refiner => refiner.LeftValueBoundString === productRefinerValue.LeftValueBoundString\r\n );\r\n refinerValueName = (filterValue ? filterValue.LeftValueBoundLocalizedString : productRefinerValue.LeftValueBoundString) || '';\r\n } else {\r\n refinerValueName = productRefinerValue.LeftValueBoundLocalizedString || productRefinerValue.LeftValueBoundString || '';\r\n }\r\n if (refinerName === 'Rating' || refinerName === 'Price' || refinerName === 'Pris') {\r\n return {\r\n key: overallFormat.replace('{0}', refinerName).replace('{1}', `${refinerValueName}`),\r\n parent:refinerName\r\n };\r\n }\r\n\r\n return {\r\n key: overallFormat.replace('{0}', refinerName).replace('{1}', `${refinerValueName}_${refinerName}_${index}`),\r\n parent:refinerName\r\n };\r\n }\r\n\r\n private _formatPrice(amount: string | undefined, currency: string | undefined): string {\r\n if (!amount || !currency) {\r\n this.props.telemetry.trace('[choice-summary] could not format price');\r\n return amount || '';\r\n }\r\n let result = amount;\r\n\r\n try {\r\n result = this.props.context!.cultureFormatter.formatCurrency(Number(amount), currency);\r\n } catch (error) {\r\n this.props.telemetry.warning(`Failed to format price for ${result}: ${error}`);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private readonly _onClick = (e: React.MouseEvent): void => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n const target = e.currentTarget as HTMLElement;\r\n const clearAll = target.getAttribute('class')!.includes('choice-summary__clear-all');\r\n const selectedRefiner = clearAll ? undefined : this._getSelectedRefinerChoice(target);\r\n\r\n if (this.props.onChoiceClicked) {\r\n this.props.onChoiceClicked({\r\n clearAll,\r\n itemClicked: target,\r\n choiceClicked: selectedRefiner,\r\n nextItemToFocus: target.nextSibling as HTMLElement\r\n });\r\n }\r\n };\r\n\r\n private _getSelectedRefinerChoice(itemClicked: HTMLElement): ProductRefinerValue | undefined {\r\n const result = this.selectedRefinersMap.find(selected => itemClicked.id === selected.key);\r\n return (result && result.value) || undefined;\r\n }\r\n}\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport * as React from 'react';\r\n\r\ninterface IErrorMessage {\r\n text?: string;\r\n}\r\n\r\nexport const ErrorMessage: React.FC = ({ text }) => {\r\n return (\r\n \r\n
\r\n {` `}\r\n {text}\r\n {` `}\r\n
\r\n
\r\n );\r\n};\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { ICoreContext, IGridSettings, IImageData, IImageSettings, Image, IRequestContext } from '@msdyn365-commerce/core';\r\nimport { SimpleProduct } from '@msdyn365-commerce/retail-proxy';\r\nimport { getFallbackImageUrl, getProductPageUrlSync } from '@msdyn365-commerce-modules/retail-actions';\r\nimport { getPayloadObject, getTelemetryAttributes, ITelemetryContent, onTelemetryClick } from '@msdyn365-commerce-modules/utilities';\r\nimport * as React from 'react';\r\n\r\nimport { IDlvrySearchResultContainerResources } from '../dlvry-search-result-container.props.autogenerated';\r\n\r\n// Import { IComponent, IComponentProps, ICoreContext, IGridSettings, IImageData, IImageSettings, Image, msdyn365Commerce } from '@msdyn365-commerce/core';\r\n\r\ninterface IFeatureSearchResultItem {\r\n product: SimpleProduct | null;\r\n context: ICoreContext;\r\n resources: IDlvrySearchResultContainerResources;\r\n imageSettings?: IImageSettings;\r\n moduleType: string;\r\n moduleId: string;\r\n telemetryContent?: ITelemetryContent;\r\n recommendation?: string;\r\n}\r\n\r\nexport const FeatureSearchResultItem: React.FC = ({\r\n product,\r\n context,\r\n imageSettings,\r\n resources,\r\n telemetryContent,\r\n recommendation\r\n}) => {\r\n if (product === null) {\r\n return null;\r\n }\r\n\r\n const productName = product.Name;\r\n const productRecordId = product && product.RecordId ? product.RecordId : 0;\r\n const productUrl = getProductPageUrlSync(product.Name || '', productRecordId, context && context.actionContext, undefined);\r\n const fallbackImage = getFallbackImageUrl(\r\n product.ItemId,\r\n context.actionContext.requestContext.apiSettings,\r\n context.request.app?.config?.OmniChannelMedia\r\n );\r\n const heading =\r\n recommendation && recommendation === 'descriptions' ? resources.featureSimilarDescriptionTitle : resources.featureSimilarLooksTitle;\r\n\r\n // Construct telemetry attribute to render\r\n const payLoad = getPayloadObject('click', telemetryContent!, productName!, productRecordId.toString());\r\n\r\n const attribute = getTelemetryAttributes(telemetryContent!, payLoad);\r\n return (\r\n
\r\n \r\n
\r\n {renderProductPlacementImage(\r\n imageSettings,\r\n context.request.gridSettings,\r\n product.PrimaryImageUrl,\r\n product.Name,\r\n fallbackImage,\r\n context.actionContext.requestContext\r\n )}\r\n
\r\n \r\n
\r\n

{heading}

\r\n {renderProductTitle(product?.Name)}\r\n
\r\n
\r\n );\r\n};\r\n\r\nfunction renderProductPlacementImage(\r\n imageSettings?: IImageSettings,\r\n gridSettings?: IGridSettings,\r\n imageUrl?: string,\r\n altText?: string,\r\n fallbackImage?: string,\r\n context?: IRequestContext\r\n): JSX.Element | null {\r\n if (!imageUrl || !gridSettings || !imageSettings) {\r\n return null;\r\n }\r\n const img: IImageData = {\r\n src: imageUrl,\r\n altText: altText ? altText : ''\r\n };\r\n const imageProps = {\r\n gridSettings,\r\n imageSettings,\r\n fallBackSrc: fallbackImage\r\n };\r\n return ;\r\n}\r\n\r\nfunction renderProductTitle(title?: string): JSX.Element | null {\r\n return

{title}

;\r\n}\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport * as React from 'react';\r\n\r\ninterface ILink {\r\n className?: string;\r\n text?: string;\r\n href?: string;\r\n ariaLabel?: string;\r\n}\r\n\r\nexport const Link: React.FC = ({ text, className, href, ariaLabel }) => (\r\n \r\n {' '}\r\n {text}{' '}\r\n \r\n);\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { Button, Modal, ModalBody, ModalFooter, ModalHeader } from '@msdyn365-commerce-modules/utilities';\r\nimport React from 'react';\r\n\r\nexport interface ISearchResultModalViewProps {\r\n modal: React.ReactElement;\r\n modalHeader: React.ReactElement;\r\n modalFooter: React.ReactElement;\r\n modalBody: React.ReactElement;\r\n}\r\n\r\ninterface IModalToggleProps {\r\n innerRef: React.RefObject | undefined;\r\n id: string;\r\n text: string;\r\n ariaLabel: string;\r\n onClick(): void;\r\n}\r\n\r\nexport interface ISearchResultModalResources {\r\n modalTitle: string;\r\n modalCloseButtonText: string;\r\n}\r\n\r\nexport interface ISearchResultModalProps {\r\n resources: ISearchResultModalResources;\r\n isOpen: boolean;\r\n returnRef: React.RefObject | undefined;\r\n onModalToggle(): void;\r\n}\r\n\r\nexport const ModalToggle: React.FC = (props: IModalToggleProps) => {\r\n const { text, onClick, ariaLabel, innerRef, id } = props;\r\n return (\r\n \r\n );\r\n};\r\n\r\nexport const SearchResultModal = (props: ISearchResultModalProps): ISearchResultModalViewProps => {\r\n return {\r\n modal: modalNode(props),\r\n modalHeader: modalHeaderNode(props),\r\n modalFooter: modalFooterNode(props),\r\n modalBody: \r\n };\r\n};\r\n\r\nconst modalNode = (props: ISearchResultModalProps) => {\r\n return (\r\n \r\n );\r\n};\r\n\r\nconst modalHeaderNode = (props: ISearchResultModalProps) => {\r\n return {props.resources.modalTitle};\r\n};\r\n\r\nconst modalFooterNode = (props: ISearchResultModalProps) => {\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\nimport { IProductsDimensionsAvailabilities } from '@msdyn365-commerce/commerce-entities';\r\nimport { IPriceComponentResources } from '@msdyn365-commerce/components';\r\nimport { ICoreContext, IImageSettings } from '@msdyn365-commerce/core';\r\nimport { CommerceList, Customer, ProductList, ProductPrice, ProductSearchResult, SimpleProduct, UnitOfMeasureConversion } from '@msdyn365-commerce/retail-proxy';\r\nimport {\r\n ArrayExtensions,\r\n ProductInput,\r\n getSimpleProducts,\r\n GetCustomerInput,\r\n getCustomer,\r\n getWishlistByCustomerId,\r\n buildWishlistLine,\r\n OrderTemplate,\r\n QueryResultSettingsProxy,\r\n GetOrderTemplatesInput,\r\n getOrderTemplates\r\n} from '@msdyn365-commerce-modules/retail-actions';\r\nimport { ICartState } from '@msdyn365-commerce/global-state';\r\nimport { ITelemetryContent } from '@msdyn365-commerce-modules/utilities';\r\nimport { addLinesAsync, createCommerceListAsync, createGetByCustomerInput, removeLinesAsync } from '@msdyn365-commerce/retail-proxy/dist/DataActions/CommerceListsDataActions.g';\r\nimport * as React from 'react';\r\nimport { ProductComponent } from '../../../themes/dlvry-adventureworks/views/components/product.component';\r\n\r\nimport { IDlvrySearchResultContainerResources } from '../dlvry-search-result-container.props.autogenerated';\r\nimport { toast, toasts } from '../../../components/toast/toast';\r\nimport PQueue from 'p-queue';\r\nimport { ValidateProductAccessResult } from '../../../shared-utils/validate-product-access';\r\nimport { IProductInventoryInformation } from '../../../components/common/product-inventory-utils';\r\nimport { onBuyHasAccessValidator } from '../../../shared-utils/attributes/on-buy-access-validator';\r\n\r\nexport interface ProductSearchResultExt extends ProductSearchResult {\r\n Badge?: string;\r\n Brand?: string;\r\n Manufacturer?: string;\r\n PrefetchedPrice?: boolean;\r\n PriceFailed?: boolean;\r\n ProductPrice?: ProductPrice;\r\n Transit?: boolean;\r\n TemperatureZone?: string;\r\n}\r\n\r\ninterface IProductSearchResultItems {\r\n cart: ICartState | undefined;\r\n products: ProductSearchResultExt[];\r\n simpleProducts: SimpleProduct[];\r\n customerInformation?: Customer;\r\n orderTemplates?: OrderTemplate[];\r\n unitConversions?: UnitOfMeasureConversion[];\r\n wishlists: CommerceList[] | undefined;\r\n context: ICoreContext;\r\n config: { [key: string]: any };\r\n resources: IDlvrySearchResultContainerResources;\r\n imageSettings?: IImageSettings;\r\n moduleType: string;\r\n moduleId: string;\r\n allowBackNavigation?: boolean;\r\n telemetryContent: ITelemetryContent;\r\n quickviewSlot?: {} | null | undefined;\r\n productComparisonButton?: {} | null | undefined;\r\n channelInventoryConfigurationId?: number;\r\n isPriceMinMaxEnabled?: boolean;\r\n productsDimensionAvailabilities?: IProductsDimensionsAvailabilities[][];\r\n productInventoryStatus?: IProductInventoryInformation[];\r\n disableBuyButtons?: boolean;\r\n showPrices?: boolean;\r\n validatedProductAccess?: ValidateProductAccessResult[];\r\n productInventoryInformation?: IProductInventoryInformation[];\r\n}\r\n\r\n/**\r\n * Returns the product inventory label.\r\n * @param channelInventoryConfigurationId - The channel configuration Id.\r\n * @param product - The product.\r\n * @param productInventoryStatus\r\n * @returns The inventory label.\r\n */\r\nexport function getInventoryLabel(channelInventoryConfigurationId: number | undefined, product: ProductSearchResult, productInventoryStatus: IProductInventoryInformation[] | undefined): string | undefined {\r\n if (productInventoryStatus) {\r\n const shippingInventory = productInventoryStatus.find(shipping => shipping.ProductAvailableQuantity.ProductId === product.RecordId);\r\n if (shippingInventory && shippingInventory.StockLevelLabel) {\r\n return shippingInventory.StockLevelLabel;\r\n }\r\n }\r\n if (!channelInventoryConfigurationId || !ArrayExtensions.hasElements(product.AttributeValues)) {\r\n return undefined;\r\n }\r\n const inventoryAttribute = product.AttributeValues.find(attribute => attribute.RecordId === channelInventoryConfigurationId);\r\n if (inventoryAttribute) {\r\n return inventoryAttribute.TextValue;\r\n }\r\n return undefined;\r\n}\r\n\r\nasync function callAddWishlistLine(context: ICoreContext, productId: number, wishlistId: number, toastErrorHeader?: string): Promise {\r\n try {\r\n const customer = await getCustomerAccount(context);\r\n if (customer && customer.AccountNumber) {\r\n const createdCommerceList = await addLinesAsync({ callerContext: context.actionContext },\r\n wishlistId,\r\n [\r\n buildWishlistLine(productId, customer.AccountNumber, wishlistId)\r\n ]);\r\n context.actionContext.update(createGetByCustomerInput({}, null), [createdCommerceList]);\r\n }\r\n } catch (err) {\r\n const error = err as unknown as any;\r\n const footer = error?.data?.CorrelationId ? `Correlation Id: ${error?.data?.CorrelationId}` : undefined;\r\n toasts.error(toastErrorHeader, error, { footer: footer });\r\n }\r\n}\r\n\r\nasync function getCustomerAccount(context: ICoreContext) {\r\n const customerInput = new GetCustomerInput(context.actionContext.requestContext.apiSettings);\r\n return getCustomer(customerInput, context.actionContext);\r\n}\r\n\r\nfunction getWishlistLineIdFromProductId(wishlists: CommerceList[] | undefined, productId: number | undefined): number | null {\r\n if (!wishlists ||\r\n !productId ||\r\n wishlists.length === 0 ||\r\n !wishlists[0].CommerceListLines ||\r\n wishlists[0].CommerceListLines.length === 0) {\r\n return null;\r\n }\r\n\r\n const foundWishlistItem = wishlists[0].CommerceListLines.filter(commerceListLine => {\r\n return commerceListLine.ProductId === productId;\r\n });\r\n\r\n if (foundWishlistItem && foundWishlistItem[0].LineId) {\r\n return foundWishlistItem[0].LineId;\r\n }\r\n return null;\r\n}\r\n\r\nasync function moveItemToWishlist(context: ICoreContext, resources: IDlvrySearchResultContainerResources, product: ProductSearchResult, defaultWishlistName: string): Promise {\r\n if (!context || !product || !context.request.user.catalogId) {\r\n return Promise.resolve();\r\n }\r\n\r\n const productInputs: ProductInput[] = [];\r\n const productInput = new ProductInput(\r\n product.RecordId,\r\n context.request.apiSettings,\r\n undefined, undefined,\r\n context.request,\r\n +context.request.user.catalogId\r\n );\r\n productInputs.push(productInput);\r\n\r\n const simpleProduct = await getSimpleProducts(productInputs, context.actionContext);\r\n\r\n if (context.request.user.isAuthenticated && simpleProduct && simpleProduct.length >= 0) {\r\n const customer = await getCustomerAccount(context);\r\n const wishlists = await getWishlistByCustomerId(createGetByCustomerInput({}, null), context.actionContext);\r\n if (!wishlists || wishlists.length === 0) {\r\n const wishlistName = defaultWishlistName;\r\n if (customer && customer.AccountNumber) {\r\n const listData: CommerceList = {\r\n CustomerId: customer.AccountNumber,\r\n Name: wishlistName,\r\n CommerceListTypeValue: 1,\r\n Id: 0\r\n };\r\n try {\r\n const commerceList = await createCommerceListAsync({\r\n callerContext: context.actionContext\r\n },\r\n listData);\r\n await callAddWishlistLine(context, simpleProduct[0].RecordId, commerceList.Id, resources.toastErrorHeader);\r\n } catch (err) {\r\n const error = err as unknown as any;\r\n const footer = error?.data?.CorrelationId ? `Correlation Id: ${error?.data?.CorrelationId}` : undefined;\r\n toasts.error(resources.toastErrorHeader, error, { footer });\r\n }\r\n }\r\n } else {\r\n await callAddWishlistLine(context, simpleProduct[0].RecordId, wishlists[0].Id, resources.toastErrorHeader);\r\n\r\n toast({\r\n text: resources.addedProductToWishlistText.replace('{productName}', simpleProduct[0].Name || ''),\r\n type: 'success',\r\n autoClose: 3000,\r\n position: 'bottom-right',\r\n canClose: true,\r\n showProgress: false\r\n });\r\n }\r\n }\r\n}\r\n\r\nfunction removeItemFromWishlist(context: ICoreContext, wishlists: CommerceList[] | undefined, product: ProductSearchResult, toastErrorHeader?: string): void {\r\n const wishlistLineId = getWishlistLineIdFromProductId(wishlists, product.RecordId);\r\n if (wishlists && wishlists[0] && wishlistLineId) {\r\n removeLinesAsync({ callerContext: context.actionContext }, wishlists[0].Id, [{ LineId: wishlistLineId }])\r\n .then(commerceList => {\r\n const newWishlists = [\r\n ...wishlists\r\n ];\r\n newWishlists[0] = commerceList;\r\n context.actionContext.update(createGetByCustomerInput({}, null), newWishlists);\r\n })\r\n .catch(error => {\r\n const footer = error?.data?.CorrelationId ? `Correlation Id: ${error?.data?.CorrelationId}` : undefined;\r\n toasts.error(toastErrorHeader, error, { footer });\r\n });\r\n }\r\n}\r\n\r\nfunction getWishlistButton(context: ICoreContext, resources: IDlvrySearchResultContainerResources, product: ProductSearchResult, wishlists: CommerceList[] | undefined, defaultWishlistName: string) {\r\n const isWishlisted = wishlists && wishlists.length > 0 && wishlists[0].CommerceListLines?.find(x => x.ProductId === product.RecordId) ? true : false;\r\n let className = 'btn-add-to-wishlist';\r\n\r\n if (isWishlisted) {\r\n className += ' is-wishlisted';\r\n }\r\n\r\n return (\r\n
\r\n {\r\n if (!isWishlisted) {\r\n await moveItemToWishlist(context, resources, product, defaultWishlistName);\r\n } else {\r\n removeItemFromWishlist(context, wishlists, product, resources.toastErrorHeader);\r\n }\r\n }\r\n }>\r\n {!isWishlisted ? resources.addToWishlistButtonText : resources.removeFromWishlistButtonText}\r\n \r\n
\r\n );\r\n}\r\n\r\nexport const ProductSearchResultItems: React.FC = ({\r\n cart,\r\n products,\r\n simpleProducts,\r\n customerInformation,\r\n orderTemplates,\r\n unitConversions,\r\n wishlists,\r\n context,\r\n config,\r\n imageSettings,\r\n resources,\r\n moduleType,\r\n moduleId,\r\n allowBackNavigation,\r\n telemetryContent,\r\n quickviewSlot,\r\n productComparisonButton,\r\n channelInventoryConfigurationId,\r\n isPriceMinMaxEnabled,\r\n productsDimensionAvailabilities,\r\n productInventoryStatus,\r\n validatedProductAccess,\r\n disableBuyButtons,\r\n showPrices,\r\n productInventoryInformation\r\n}) => {\r\n const [orderTemplatesState, setOrderTemplatesState] = React.useState(undefined);\r\n const cartQueue = React.useMemo(() => new PQueue({ concurrency: 1 }), []);\r\n\r\n const updateOrderTemplatesAsync = async (newOrderTemplate?: ProductList) => {\r\n let newOrderTemplates;\r\n\r\n if (newOrderTemplate) {\r\n newOrderTemplates = [...(orderTemplatesState ? orderTemplatesState : orderTemplates ? orderTemplates : [])];\r\n\r\n // Add new order template if it doesn't exist\r\n if (newOrderTemplates.every(x => x.productList.Id !== newOrderTemplate.Id)) {\r\n newOrderTemplates.splice(0, 0, new OrderTemplate(newOrderTemplate, [], 0));\r\n }\r\n } else {\r\n // Refresh order templates incase new order template was created\r\n const queryResultSettings = QueryResultSettingsProxy.fromInputData({\r\n requestContext: context.request,\r\n config: config\r\n }).QueryResultSettings;\r\n const input = new GetOrderTemplatesInput('', queryResultSettings);\r\n newOrderTemplates = (await getOrderTemplates(input, context.actionContext)).map(x => new OrderTemplate(x, [], 0));\r\n }\r\n\r\n setOrderTemplatesState(newOrderTemplates);\r\n return newOrderTemplates;\r\n };\r\n\r\n const retrieveOrderTemplates = async () => {\r\n return orderTemplates ? orderTemplates : orderTemplatesState ? orderTemplatesState : updateOrderTemplatesAsync();\r\n };\r\n\r\n const priceResources: IPriceComponentResources = {\r\n priceRangeSeparator: resources.priceRangeSeparator\r\n };\r\n return (\r\n
    \r\n {products.map((product: ProductSearchResultExt, index: number) => (\r\n
  • \r\n x.RecordId === product.RecordId),\r\n customerInformation,\r\n unitConversions: unitConversions?.filter(x => x.ProductRecordId === product.RecordId)\r\n }}\r\n cartQueue={cartQueue}\r\n buyAlwaysAdd\r\n retrieveOrderTemplates={retrieveOrderTemplates}\r\n onUpdateOrderTemplates={updateOrderTemplatesAsync}\r\n quickViewButton={quickviewSlot}\r\n productComparisonButton={productComparisonButton}\r\n wishlistButton={getWishlistButton(context, resources, product, wishlists, resources.defaultWishlistName)}\r\n inventoryLabel={getInventoryLabel(channelInventoryConfigurationId, product,productInventoryStatus)}\r\n inventoryStatus={productInventoryInformation?.find(x => x.ProductAvailableQuantity.ProductId === product.RecordId)}\r\n isPriceMinMaxEnabled={isPriceMinMaxEnabled}\r\n disableBuyButton={disableBuyButtons}\r\n showPrice={showPrices}\r\n userHasAccess={validatedProductAccess?.find(x => x.RecordId === product.RecordId)?.HasAccess}\r\n priceResources={priceResources}\r\n swatchItemAriaLabel={resources.swatchItemAriaLabel}\r\n addToCartText={resources.addToCartText}\r\n updateCartText={resources.updateCartText}\r\n removeFromCartText={resources.removeFromCartText}\r\n outOfStockText={resources.outOfStockText}\r\n priceErrorText={resources.priceErrorText}\r\n toastStrings={{\r\n errorHeader: resources.toastErrorHeader,\r\n productsAddedToCart: resources.productsAddedToCart,\r\n productsRemovedFromCart: resources.productsRemovedFromCart,\r\n productsUpdatedInCart: resources.productsUpdatedInCart,\r\n goToCart: resources.toastGoToCart,\r\n noAccessToProduct: resources.toastNoAccessToProduct\r\n }}\r\n inCartTooltipText={resources.inCartTooltipText}\r\n transitTooltip={resources.transitTooltip}\r\n dimensionAvailabilities={productsDimensionAvailabilities?.find(\r\n dimensionAvailability =>\r\n ArrayExtensions.hasElements(dimensionAvailability) &&\r\n dimensionAvailability[0].masterProductId === product.MasterProductId\r\n )}\r\n addToOrderTemplateResources={{\r\n addToOrderTemplateHeader: resources.addToOrderTemplateHeader,\r\n noOrderTemplatesMessage: resources.noOrderTemplatesMessage,\r\n noOrderTemplatesDescription: resources.noOrderTemplatesDescription,\r\n createAnOrderTemplateButtonText: resources.createAnOrderTemplateButtonText,\r\n createNewOrderTemplateButtonText: resources.createNewOrderTemplateButtonText,\r\n cancelOrderTemplateCreationButtonText: resources.cancelOrderTemplateCreationButtonText,\r\n selectTemplatesText: resources.selectTemplatesText,\r\n addToTemplateButtonText: resources.addToTemplateButtonText,\r\n lineItemsText: resources.lineItemsText,\r\n createOrderTemplateHeader: resources.createOrderTemplateHeader,\r\n orderTemplateTitle: resources.orderTemplateTitle,\r\n orderTemplateNameAriaLabel: resources.orderTemplateNameAriaLabel,\r\n createOrderTemplateDescription: resources.createOrderTemplateDescription,\r\n defaultOrderTemplateName: resources.defaultOrderTemplateName,\r\n createOrderTemplateButtonText: resources.createOrderTemplateButtonText,\r\n cancelNewOrderTemplateCreationButtonText: resources.cancelNewOrderTemplateCreationButtonText,\r\n viewOrderTemplateButtonText: resources.viewOrderTemplateButtonText,\r\n continueShoppingButtonText: resources.continueShoppingButtonText,\r\n itemAddedToOrderTemplateHeaderItemOneText: resources.itemAddedToOrderTemplateHeaderItemOneText,\r\n itemAddedToOrderTemplateHeaderItemFormatText: resources.itemAddedToOrderTemplateHeaderItemFormatText,\r\n itemAddedToOrderTemplateHeaderMessageText: resources.itemAddedToOrderTemplateHeaderMessageText,\r\n priceFree: resources.priceFree,\r\n originalPriceText: resources.originalPriceText,\r\n currentPriceText: resources.currentPriceText,\r\n duplicatedProductsHeader: resources.duplicatedProductsHeader,\r\n duplicatedProductsDescription: resources.duplicatedProductsDescription,\r\n updateQuantityButtonText: resources.updateQuantityButtonText,\r\n cancelDuplicateItemsButtonText: resources.cancelDuplicateItemsButtonText,\r\n addToOrderTemplateButtonText: resources.addToOrderTemplateButtonText,\r\n addToOrderTemplateButtonTooltip: resources.addToOrderTemplateButtonTooltip\r\n }}\r\n onBuyValidate={(product) => onBuyHasAccessValidator(\r\n context,\r\n customerInformation,\r\n product,\r\n resources.toastNoAccessToProduct\r\n )}\r\n />\r\n
  • \r\n ))}\r\n
\r\n );\r\n};\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport * as React from 'react';\r\n\r\ninterface ISeparator {\r\n separator: string;\r\n}\r\n\r\nexport const Separator: React.FC = ({ separator }) => (\r\n \r\n {` `}\r\n {separator}\r\n {` `}\r\n \r\n);\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport * as React from 'react';\r\n\r\ninterface ITitle {\r\n className: string;\r\n text: string;\r\n}\r\n\r\nexport const Title: React.FC = ({ text, className }) => (\r\n \r\n {` `}\r\n {text}\r\n {` `}\r\n \r\n);\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\nimport { observer } from 'mobx-react';\r\nimport * as React from 'react';\r\n\r\nimport { isUndefined } from 'lodash';\r\nimport { ProductRefinerValue } from '@msdyn365-commerce/retail-proxy';\r\nimport { Button } from '@msdyn365-commerce-modules/utilities';\r\nimport { IRefineItemState } from './refine-item';\r\nimport { isCustomRangeTypeIntegerSelected } from './utilities';\r\nimport { IProductRefinerHierarchy } from '@msdyn365-commerce/commerce-entities';\r\nimport { IRefineItemCommonProps } from './refine-item.props.common';\r\nimport { IRefineItemToggleNotification } from './refine-item-toggle-notification';\r\n\r\nexport type RangeRefineItemInputType = 'slider' | 'input';\r\n\r\n/**\r\n * Range refine item properties.\r\n */\r\nexport interface IRangeRefineItemInputProps {\r\n parentProductRefinerHierarchy: IProductRefinerHierarchy;\r\n selectedRefinementCriterion: ProductRefinerValue | undefined;\r\n refineItemCommonProps: IRefineItemCommonProps;\r\n isDisabled: boolean;\r\n rangeType: RangeRefineItemInputType;\r\n\r\n /**\r\n * The telemetry content\r\n */\r\n onToggle(notfication: Readonly): void;\r\n}\r\n\r\n/**\r\n * Range refine item state.\r\n */\r\nexport interface IRangeRefineItemInputState extends IRefineItemState {\r\n validationErrorMin: string | undefined;\r\n validationErrorMax: string | undefined;\r\n selectedMin: string | undefined;\r\n selectedMax: string | undefined;\r\n invalidData: boolean | undefined;\r\n}\r\n\r\n/**\r\n * RangeRefineItem component (controlled by RefineSubmenu).\r\n */\r\n@observer\r\nexport default class RangeRefineItemInput extends React.Component {\r\n private readonly _formattedPriceReverseLookup: Map = new Map();\r\n\r\n private readonly minInput: React.RefObject;\r\n\r\n private readonly maxInput: React.RefObject;\r\n\r\n public constructor(props: IRangeRefineItemInputProps) {\r\n super(props);\r\n this._changeMinInputRange = this._changeMinInputRange.bind(this);\r\n this._changeMaxInputRange = this._changeMaxInputRange.bind(this);\r\n this._applyCustom = this._applyCustom.bind(this);\r\n\r\n this.minInput = React.createRef();\r\n this.maxInput = React.createRef();\r\n let initialMin = '';\r\n let initialMax = '';\r\n const { selectedRefinementCriterion, parentProductRefinerHierarchy } = this.props;\r\n if (selectedRefinementCriterion) {\r\n initialMin = isCustomRangeTypeIntegerSelected(selectedRefinementCriterion, parentProductRefinerHierarchy)\r\n ? ''\r\n : selectedRefinementCriterion?.LeftValueBoundString || '';\r\n initialMax = isCustomRangeTypeIntegerSelected(selectedRefinementCriterion, parentProductRefinerHierarchy)\r\n ? ''\r\n : selectedRefinementCriterion?.RightValueBoundString || '';\r\n }\r\n\r\n this.state = {\r\n validationErrorMin: undefined,\r\n validationErrorMax: undefined,\r\n selectedMin: initialMin,\r\n selectedMax: initialMax,\r\n invalidData: !(initialMin && initialMax),\r\n isChecked: false\r\n };\r\n }\r\n\r\n public shouldComponentUpdate(nextProps: IRangeRefineItemInputProps, nextState: IRangeRefineItemInputState): boolean {\r\n if (this.state === nextState && this.props === nextProps) {\r\n return false;\r\n }\r\n nextState.invalidData = !(nextState.selectedMin && nextState.selectedMax);\r\n return true;\r\n }\r\n\r\n public componentDidUpdate(previousProps: IRangeRefineItemInputProps): void {\r\n if (previousProps !== this.props) {\r\n this.updateInputRangerProps();\r\n }\r\n }\r\n\r\n public render(): JSX.Element | undefined {\r\n if (this.props.rangeType === 'input') {\r\n return this._renderInputFields();\r\n }\r\n return undefined;\r\n }\r\n\r\n // /**\r\n // * Function to update slider props.\r\n // */\r\n private updateInputRangerProps(): void {\r\n const selectedMin = !isUndefined(this.props.selectedRefinementCriterion?.RowNumber)\r\n ? ''\r\n : this.props.selectedRefinementCriterion?.LeftValueBoundString;\r\n const selectedMax = !isUndefined(this.props.selectedRefinementCriterion?.RowNumber)\r\n ? ''\r\n : this.props.selectedRefinementCriterion?.RightValueBoundString;\r\n this.setState({ selectedMin, selectedMax });\r\n }\r\n\r\n private _renderInputFields(): JSX.Element | undefined {\r\n const { isDisabled, parentProductRefinerHierarchy, refineItemCommonProps } = this.props;\r\n const { validationErrorMin, validationErrorMax } = this.state;\r\n\r\n const rangeAriaLabel = (refineItemCommonProps.rangeNameFormat || '{0}').replace('{0}', parentProductRefinerHierarchy.KeyName || '');\r\n const formAttrs = {\r\n 'aria-label': rangeAriaLabel,\r\n 'aria-disabled': isDisabled\r\n };\r\n\r\n const minInputClassName = `ms-refine-submenu__input-range refine-submenu__input-range-min ${\r\n validationErrorMin ? 'refine-submenu__input-range--error' : ''\r\n }`;\r\n const maxInputClassName = `ms-refine-submenu__input-range refine-submenu__input-range-max ${\r\n validationErrorMax ? 'refine-submenu__input-range--error' : ''\r\n }`;\r\n return (\r\n
  • \r\n
    \r\n
    \r\n \r\n {' - '}\r\n \r\n {validationErrorMin && (\r\n \r\n {validationErrorMin}\r\n \r\n )}\r\n {validationErrorMax && validationErrorMin !== validationErrorMax && (\r\n \r\n {validationErrorMax}\r\n \r\n )}\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
  • \r\n );\r\n }\r\n\r\n private _applyCustom(event: React.MouseEvent): void {\r\n const selectedMinValue = this._getInputWithoutFormatting(this.state.selectedMin || '');\r\n this.setState({\r\n selectedMin: selectedMinValue,\r\n minTouched: false\r\n });\r\n const minInput = Number(selectedMinValue);\r\n const { onToggle, parentProductRefinerHierarchy } = this.props;\r\n const max = this.state.selectedMax;\r\n\r\n const maxNum = max ? Number(max) : undefined;\r\n const productRefinerValue: ProductRefinerValue = {\r\n RefinerRecordId: parentProductRefinerHierarchy.Values[0].RefinerRecordId,\r\n LeftValueBoundString: this.state.selectedMin,\r\n RightValueBoundString: this.state.selectedMax,\r\n DataTypeValue: parentProductRefinerHierarchy.DataTypeValue,\r\n RefinerSourceValue: parentProductRefinerHierarchy.Values[0].RefinerSourceValue\r\n };\r\n\r\n if (this._validateRange(minInput, maxNum)) {\r\n onToggle({\r\n parentProductRefinerHierarchy,\r\n productRefinerValue,\r\n isSelecting: true\r\n });\r\n }\r\n }\r\n\r\n private _changeMinInputRange(event: React.ChangeEvent): void {\r\n this.setState({\r\n selectedMin: event.target.value.trim()\r\n });\r\n }\r\n\r\n private _changeMaxInputRange(event: React.ChangeEvent): void {\r\n this.setState({\r\n selectedMax: event.target.value.trim()\r\n });\r\n }\r\n\r\n private _validateRange(min: number, max: number | undefined): boolean {\r\n const { refineItemCommonProps } = this.props;\r\n if (max === undefined) {\r\n return true;\r\n }\r\n\r\n if (min > max) {\r\n this.setState({\r\n validationErrorMin: refineItemCommonProps.validationErrorRange,\r\n validationErrorMax: refineItemCommonProps.validationErrorRange\r\n });\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private _getInputWithoutFormatting(input: string): string {\r\n // First try to cast raw input to a number\r\n const inputAsNum = Number(input);\r\n if (!isNaN(inputAsNum)) {\r\n return input;\r\n }\r\n\r\n // Otherwise try a reverse lookup and fall back to the raw input if all else fails\r\n const reverseLookupResult = this._formattedPriceReverseLookup.get(input);\r\n return reverseLookupResult || input;\r\n }\r\n}\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { ISliderLabel, ISliderThumbProps, Slider } from '@msdyn365-commerce-modules/utilities';\r\nimport debounce from 'lodash/debounce';\r\nimport { computed } from 'mobx';\r\nimport { observer } from 'mobx-react';\r\nimport * as React from 'react';\r\n\r\nimport { IRefineItemProps, IRefineItemState } from './refine-item';\r\n\r\ntype InputType = 'Min' | 'Max';\r\n\r\nexport type RangeRefineItemType = 'slider' | 'input';\r\n\r\n/**\r\n * Range refine item properties.\r\n */\r\nexport interface IRangeRefineItemProps extends IRefineItemProps {\r\n rangeType: RangeRefineItemType;\r\n minValueSliderThumbAriaLabel?: string;\r\n maxValueSliderThumbAriaLabel?: string;\r\n sliderKey?: string;\r\n}\r\n\r\n/**\r\n * Range refine item state.\r\n */\r\nexport interface IRangeRefineItemState extends IRefineItemState {\r\n validationErrorMin: string | undefined;\r\n validationErrorMax: string | undefined;\r\n selectedMin: string | undefined;\r\n selectedMax: string | undefined;\r\n touchedMin: boolean;\r\n touchedMax: boolean;\r\n sliderId: string;\r\n minValue: string | undefined;\r\n maxValue: string | undefined;\r\n labels: ISliderLabel[];\r\n sliderThumbs: ISliderThumbProps[];\r\n}\r\n\r\n/**\r\n * RangeRefineItem component (controlled by RefineSubmenu).\r\n */\r\n@observer\r\nexport default class RangeRefineItem extends React.Component {\r\n private readonly _formattedPriceReverseLookup: Map = new Map();\r\n\r\n private readonly minInput: React.RefObject;\r\n\r\n private readonly maxInput: React.RefObject;\r\n\r\n @computed get currencyCode(): string {\r\n return this.props.productRefinerValue.UnitText || '';\r\n }\r\n\r\n public constructor(props: IRangeRefineItemProps) {\r\n super(props);\r\n this._onRangeUpdate = this._onRangeUpdate.bind(this);\r\n this._onRangeUpdateEnd = this._onRangeUpdateEnd.bind(this);\r\n this._handleRangeTooltipText = this._handleRangeTooltipText.bind(this);\r\n this._changeMin = this._changeMin.bind(this);\r\n this._changeMax = this._changeMax.bind(this);\r\n this._finishChangeMin = this._finishChangeMin.bind(this);\r\n this._finishChangeMax = this._finishChangeMax.bind(this);\r\n\r\n this.minInput = React.createRef();\r\n this.maxInput = React.createRef();\r\n\r\n const { selectedRefinementCriterion } = this.props;\r\n const initialMin = selectedRefinementCriterion?.LeftValueBoundString ?? '0';\r\n const initialMax = selectedRefinementCriterion?.RightValueBoundString;\r\n const sliderId = `slider_${String(this.props.parentProductRefinerHierarchy.RecordId)}_${String(\r\n this.props.productRefinerValue.RefinerRecordId\r\n )}`;\r\n const minValue = this.props.productRefinerValue.LeftValueBoundString;\r\n const maxValue = this.props.productRefinerValue.RightValueBoundString;\r\n const minPrice = this._formatPrice(minValue);\r\n const maxPrice = this._formatPrice(maxValue);\r\n const labels: ISliderLabel[] = this.getLabels(sliderId, minPrice, maxPrice);\r\n const selectedMin =\r\n this.props.selectedRefinementCriterion?.LeftValueBoundString ?? this.props.productRefinerValue.LeftValueBoundString ?? '0';\r\n const selectedMax =\r\n this.props.selectedRefinementCriterion?.RightValueBoundString ??\r\n this.props.productRefinerValue.RightValueBoundString ??\r\n maxValue;\r\n const selectedMinPrice = this._formatPrice(selectedMin);\r\n const selectedMaxPrice = this._formatPrice(selectedMax);\r\n const sliderKeyString = this.props.sliderKey ? `_${String(this.props.sliderKey)}` : '';\r\n const sliderThumbs: ISliderThumbProps[] = this.getSliderThumbs(\r\n sliderId,\r\n sliderKeyString,\r\n selectedMin,\r\n selectedMinPrice,\r\n selectedMax,\r\n selectedMaxPrice,\r\n maxPrice\r\n );\r\n this.state = {\r\n isChecked: false,\r\n validationErrorMin: undefined,\r\n validationErrorMax: undefined,\r\n selectedMin: initialMin,\r\n selectedMax: initialMax,\r\n touchedMin: false,\r\n touchedMax: false,\r\n sliderId,\r\n minValue,\r\n maxValue,\r\n labels,\r\n sliderThumbs\r\n };\r\n }\r\n\r\n public shouldComponentUpdate(nextProps: IRangeRefineItemProps, nextState: IRangeRefineItemState): boolean {\r\n if (this.state === nextState && this.props === nextProps) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n public componentDidUpdate(previousProps: IRangeRefineItemProps): void {\r\n if (previousProps !== this.props) {\r\n this.updateSliderProps();\r\n }\r\n }\r\n\r\n public render(): JSX.Element | undefined {\r\n const { productRefinerValue, parentProductRefinerHierarchy, refineItemCommonProps } = this.props;\r\n\r\n if (!productRefinerValue || !parentProductRefinerHierarchy) {\r\n refineItemCommonProps.telemetry.error(\r\n 'Cannot render refine value range without productRefinerValue and parentProductRefinerHierarchy'\r\n );\r\n return undefined;\r\n }\r\n\r\n if (this.props.rangeType === 'input') {\r\n return this._renderInputFields();\r\n }\r\n\r\n return this._renderSlider();\r\n }\r\n\r\n /**\r\n * Function to update slider props.\r\n */\r\n private updateSliderProps(): void {\r\n const sliderId = `slider_${String(this.props.parentProductRefinerHierarchy.RecordId)}_${String(\r\n this.props.productRefinerValue.RefinerRecordId\r\n )}`;\r\n const minValue = this.props.productRefinerValue.LeftValueBoundString;\r\n const maxValue = this.props.productRefinerValue.RightValueBoundString;\r\n const minPrice = this._formatPrice(minValue);\r\n const maxPrice = this._formatPrice(maxValue);\r\n const labels: ISliderLabel[] = this.getLabels(sliderId, minPrice, maxPrice);\r\n const selectedMin =\r\n this.props.selectedRefinementCriterion?.LeftValueBoundString ?? this.props.productRefinerValue.LeftValueBoundString ?? '0';\r\n const selectedMax =\r\n this.props.selectedRefinementCriterion?.RightValueBoundString ??\r\n this.props.productRefinerValue.RightValueBoundString ??\r\n maxValue;\r\n const selectedMinPrice = this._formatPrice(selectedMin);\r\n const selectedMaxPrice = this._formatPrice(selectedMax);\r\n const sliderKeyString = this.props.sliderKey ? `_${String(this.props.sliderKey)}` : '';\r\n const sliderThumbs: ISliderThumbProps[] = this.getSliderThumbs(\r\n sliderId,\r\n sliderKeyString,\r\n selectedMin,\r\n selectedMinPrice,\r\n selectedMax,\r\n selectedMaxPrice,\r\n maxPrice\r\n );\r\n this.setState({ sliderId, minValue, maxValue, labels, sliderThumbs });\r\n }\r\n\r\n /**\r\n * Function to create the labels for slider.\r\n * @param sliderId - Slider element id for the DOM.\r\n * @param minPrice - Slider min value.\r\n * @param maxPrice - Slider max value.\r\n * @returns Array labels.\r\n */\r\n private readonly getLabels = (sliderId: string, minPrice: string, maxPrice: string): ISliderLabel[] => {\r\n return [\r\n {\r\n labelId: `${sliderId}_start`,\r\n labelString: `${minPrice}`,\r\n labelPositioning: 'start'\r\n },\r\n {\r\n labelId: `${sliderId}_end`,\r\n labelString: `${maxPrice}`,\r\n labelPositioning: 'end'\r\n }\r\n ];\r\n };\r\n\r\n /**\r\n * Function to create the slider thumbs for slider.\r\n * @param sliderId - Slider element id for the DOM.\r\n * @param sliderKey - Unique key for slider.\r\n * @param selectedMin - Slider selected min value.\r\n * @param selectedMinPrice - Slider selected min price.\r\n * @param selectedMax - Slider selected max value.\r\n * @param selectedMaxPrice - Slider selected max price..\r\n * @param maxPrice - Slider max price..\r\n * @returns Slider Thumb Props.\r\n */\r\n private readonly getSliderThumbs = (\r\n sliderId: string,\r\n sliderKey: string,\r\n selectedMin: string,\r\n selectedMinPrice: string,\r\n selectedMax: string | undefined,\r\n selectedMaxPrice: string,\r\n maxPrice: string\r\n ): ISliderThumbProps[] => {\r\n const sliderThumbDefaultValue = 0;\r\n return [\r\n {\r\n id: `${sliderId}${sliderKey}_slider_thumb_start`,\r\n value: (selectedMin && Number(selectedMin)) || sliderThumbDefaultValue,\r\n ariaLabel: `${this.props.minValueSliderThumbAriaLabel ?? ''} ${this.currencyCode}`,\r\n ariaValueText: `${selectedMinPrice}`\r\n },\r\n {\r\n id: `${sliderId}${sliderKey}_slider_thumb_end`,\r\n value: Number(selectedMax) || Number(maxPrice),\r\n ariaLabel: `${this.props.maxValueSliderThumbAriaLabel ?? ''} ${this.currencyCode}`,\r\n ariaValueText: `${selectedMaxPrice}`\r\n }\r\n ];\r\n };\r\n\r\n private _renderInputFields(): JSX.Element | undefined {\r\n const { isDisabled, parentProductRefinerHierarchy, refineItemCommonProps } = this.props;\r\n const { selectedMin, selectedMax, touchedMin, touchedMax, validationErrorMin, validationErrorMax } = this.state;\r\n\r\n const rangeAriaLabel = (refineItemCommonProps.rangeNameFormat || '{0}').replace('{0}', parentProductRefinerHierarchy.KeyName || '');\r\n const formAttrs = {\r\n 'aria-label': rangeAriaLabel,\r\n 'aria-disabled': isDisabled\r\n };\r\n\r\n // To enable price formatting of selected fields, this is the approach:\r\n // initial value: min=0 formatted as price, max=undefined\r\n // onFocus/onChange: convert to number (unformat) and mark as touched to indicate value is being edited\r\n // onBlur: validate and format entered value as price\r\n const minInputClassName = `ms-refine-submenu__input-range refine-submenu__input-range-min ${\r\n validationErrorMin ? 'refine-submenu__input-range--error' : ''\r\n }`;\r\n const maxInputClassName = `ms-refine-submenu__input-range refine-submenu__input-range-max ${\r\n validationErrorMax ? 'refine-submenu__input-range--error' : ''\r\n }`;\r\n const minLabelClassName = 'ms-refine-submenu__input-range-label refine-submenu__input-range-label-min';\r\n const maxLabelClassName = 'ms-refine-submenu__input-range-label refine-submenu__input-range-label-max';\r\n const formattedSelectedMin = this._getFormattedSelectedValue(selectedMin, touchedMin, validationErrorMin);\r\n const formattedSelectedMax = this._getFormattedSelectedValue(selectedMax, touchedMax, validationErrorMax);\r\n return (\r\n
    \r\n \r\n \r\n {validationErrorMin && (\r\n \r\n {validationErrorMin}\r\n \r\n )}\r\n {validationErrorMax && validationErrorMin !== validationErrorMax && (\r\n \r\n {validationErrorMax}\r\n \r\n )}\r\n
    \r\n );\r\n }\r\n\r\n private _renderSlider(): JSX.Element | undefined {\r\n const { isDisabled, sliderKey } = this.props;\r\n const ariaAttributes = {\r\n 'aria-disabled': isDisabled\r\n };\r\n\r\n return (\r\n \r\n );\r\n }\r\n\r\n private _changeMin(event: React.FocusEvent): void {\r\n this._changeValue(event, 'Min');\r\n }\r\n\r\n private _changeMax(event: React.FocusEvent): void {\r\n this._changeValue(event, 'Max');\r\n }\r\n\r\n private _changeValue(event: React.FocusEvent, inputType: InputType): void {\r\n const selectedKey = `selected${inputType}`;\r\n const touchedKey = `touched${inputType}`;\r\n this.setState({\r\n [selectedKey]: this._getInputWithoutFormatting(event.currentTarget.value),\r\n [touchedKey]: true\r\n });\r\n }\r\n\r\n private _finishChangeMin(event: React.FocusEvent): boolean {\r\n const selectedMinValue = this._getInputWithoutFormatting(event.currentTarget.value);\r\n this.setState({\r\n selectedMin: selectedMinValue,\r\n minTouched: false\r\n });\r\n const minInput = Number(selectedMinValue);\r\n const {\r\n onToggle,\r\n parentProductRefinerHierarchy,\r\n productRefinerValue,\r\n refineItemCommonProps,\r\n selectedRefinementCriterion\r\n } = this.props;\r\n const max = (selectedRefinementCriterion && selectedRefinementCriterion.RightValueBoundString) || undefined;\r\n\r\n const maxNum = max ? Number(max) : undefined;\r\n\r\n if (isNaN(minInput)) {\r\n this.setState({ validationErrorMin: refineItemCommonProps.validationErrorNaN });\r\n this._focus('Min');\r\n return false;\r\n }\r\n\r\n if (this._validateRange(minInput, maxNum)) {\r\n onToggle({\r\n parentProductRefinerHierarchy,\r\n productRefinerValue,\r\n isSelecting: true,\r\n rangeStart: minInput,\r\n rangeEnd: maxNum\r\n });\r\n return true;\r\n }\r\n this._focus('Min');\r\n\r\n return false;\r\n }\r\n\r\n private _finishChangeMax(event: React.FocusEvent): boolean {\r\n const selectedMaxValue = this._getInputWithoutFormatting(event.currentTarget.value);\r\n this.setState({\r\n selectedMax: selectedMaxValue,\r\n maxTouched: false\r\n });\r\n const maxInput = Number(selectedMaxValue);\r\n const {\r\n onToggle,\r\n parentProductRefinerHierarchy,\r\n productRefinerValue,\r\n refineItemCommonProps,\r\n selectedRefinementCriterion\r\n } = this.props;\r\n const min = (selectedRefinementCriterion && selectedRefinementCriterion.LeftValueBoundString) || '0';\r\n\r\n const minNum = Number(min);\r\n\r\n if (isNaN(maxInput)) {\r\n this.setState({ validationErrorMax: refineItemCommonProps.validationErrorNaN });\r\n this._focus('Max');\r\n return false;\r\n }\r\n\r\n if (this._validateRange(minNum, maxInput)) {\r\n if (productRefinerValue) {\r\n onToggle({\r\n parentProductRefinerHierarchy,\r\n productRefinerValue,\r\n isSelecting: true,\r\n rangeStart: minNum,\r\n rangeEnd: maxInput\r\n });\r\n } else {\r\n this._focus('Max');\r\n }\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private _focus(inputType: InputType): void {\r\n const ref = inputType === 'Max' ? this.maxInput : this.minInput;\r\n\r\n setTimeout(() => {\r\n if (ref && ref.current) {\r\n ref.current.focus();\r\n }\r\n }, 50);\r\n }\r\n\r\n private _getFormattedSelectedValue(\r\n selected: string | undefined,\r\n touched: boolean,\r\n validationError: string | undefined\r\n ): string | undefined {\r\n if (touched || validationError || selected === undefined) {\r\n return selected;\r\n }\r\n return this._formatPrice(selected);\r\n }\r\n\r\n private _validateRange(min: number, max: number | undefined): boolean {\r\n const { refineItemCommonProps } = this.props;\r\n if (max === undefined) {\r\n return true;\r\n }\r\n\r\n if (min > max) {\r\n this.setState({\r\n validationErrorMin: refineItemCommonProps.validationErrorRange,\r\n validationErrorMax: refineItemCommonProps.validationErrorRange\r\n });\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private _formatPrice(amount: string | undefined): string {\r\n if (this.props.productRefinerValue.RefinerRecordId === 0) {\r\n const result = this.props.context.cultureFormatter.formatCurrency(Number(amount), this.currencyCode);\r\n return result;\r\n }\r\n return amount || '';\r\n }\r\n\r\n private _getInputWithoutFormatting(input: string): string {\r\n // First try to cast raw input to a number\r\n const inputAsNum = Number(input);\r\n if (!isNaN(inputAsNum)) {\r\n return input;\r\n }\r\n\r\n // Otherwise try a reverse lookup and fall back to the raw input if all else fails\r\n const reverseLookupResult = this._formattedPriceReverseLookup.get(input);\r\n return reverseLookupResult || input;\r\n }\r\n\r\n // NOTE: Fix types once Shared Components build pipeline bug fixed\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n private _onRangeUpdate(sliderChangeNotification: any): void {\r\n // Need to filter out mousemove events as these cause errors after the menu updates and slider re-renders\r\n if (sliderChangeNotification.eventType !== 'mousemove') {\r\n const { onToggle, parentProductRefinerHierarchy, productRefinerValue } = this.props;\r\n if (productRefinerValue && sliderChangeNotification) {\r\n onToggle({\r\n parentProductRefinerHierarchy,\r\n productRefinerValue,\r\n isSelecting: true,\r\n rangeStart: sliderChangeNotification.firstThumbValue,\r\n rangeEnd: sliderChangeNotification.secondThumbValue\r\n });\r\n\r\n this._focusOnSliderThumb(sliderChangeNotification);\r\n }\r\n }\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n private _onRangeUpdateEnd(sliderChangeNotification: any): void {\r\n const { onToggle, parentProductRefinerHierarchy, productRefinerValue } = this.props;\r\n if (productRefinerValue && sliderChangeNotification) {\r\n onToggle({\r\n parentProductRefinerHierarchy,\r\n productRefinerValue,\r\n isSelecting: true,\r\n rangeStart: sliderChangeNotification.firstThumbValue,\r\n rangeEnd: sliderChangeNotification.secondThumbValue\r\n });\r\n\r\n this._focusOnSliderThumb(sliderChangeNotification);\r\n }\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n private _focusOnSliderThumb(sliderChangeNotification: any): void {\r\n if (sliderChangeNotification.id) {\r\n const element = document.getElementById(`${sliderChangeNotification.id}range`);\r\n if (element) {\r\n setTimeout(() => {\r\n element.focus();\r\n }, 0);\r\n }\r\n }\r\n }\r\n\r\n private _handleRangeTooltipText(tooltip: number): string {\r\n return this._formatPrice(`${tooltip}`);\r\n }\r\n}\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { IProductRefinerHierarchy } from '@msdyn365-commerce/commerce-entities';\r\nimport { RatingComponent, SwatchComponent } from '@msdyn365-commerce/components';\r\nimport { IAny, ICoreContext, IGeneric } from '@msdyn365-commerce/core';\r\nimport { ProductRefinerSource, ProductRefinerValue, RefinerType } from '@msdyn365-commerce/retail-proxy';\r\nimport { checkIfShouldDisplayAsSwatch, DimensionTypes, IDimensionsApp, StringExtensions } from '@msdyn365-commerce-modules/retail-actions';\r\nimport { format, getPayloadObject, getTelemetryAttributes, IPayLoad, ITelemetryContent } from '@msdyn365-commerce-modules/utilities';\r\nimport classnames from 'classnames';\r\nimport * as React from 'react';\r\n\r\nimport { IRefineItemCommonProps } from './refine-item.props.common';\r\nimport { IRefineItemToggleNotification } from './refine-item-toggle-notification';\r\n\r\n/**\r\n * RefineItem properties.\r\n */\r\nexport interface IRefineItemProps {\r\n parentProductRefinerHierarchy: IProductRefinerHierarchy;\r\n productRefinerValue: ProductRefinerValue;\r\n selectedRefinementCriterion: ProductRefinerValue | undefined;\r\n selectedRefinerValues?: ProductRefinerValue[];\r\n refineItemCommonProps: IRefineItemCommonProps;\r\n isDisabled: boolean;\r\n context: ICoreContext>;\r\n moduleId: string;\r\n moduleTypeName: string;\r\n index?: number;\r\n productCountAriaLabel?: string;\r\n singleProductCountAriaLabel?: string;\r\n refineItemAriaLabel?: string;\r\n refineItemsAriaLabel?: string;\r\n isMobileView?: boolean;\r\n yesText?: string;\r\n noText?: string;\r\n transitRefinerRecordId?: string;\r\n\r\n /**\r\n * The telemetry content\r\n */\r\n telemetryContent?: ITelemetryContent;\r\n onToggle(notfication: Readonly): void;\r\n urlBuilder(refiner: IRefineItemToggleNotification): string;\r\n}\r\n\r\n/**\r\n * Refine item state.\r\n */\r\nexport interface IRefineItemState extends React.ComponentState {\r\n isChecked: boolean;\r\n renderingError?: object;\r\n}\r\n\r\n/**\r\n * Single-select and multi-select refine item component (controlled by RefineSubmenu).\r\n */\r\nexport default class RefineItem extends React.Component {\r\n private readonly anchorType: React.RefObject;\r\n\r\n private readonly payLoad: IPayLoad;\r\n\r\n public constructor(props: IRefineItemProps) {\r\n super(props);\r\n this._onClick = this._onClick.bind(this);\r\n this.state = {\r\n isChecked: !!this.props.selectedRefinementCriterion\r\n };\r\n this.anchorType = React.createRef();\r\n this.payLoad = getPayloadObject('click', this.props.telemetryContent!, '');\r\n }\r\n\r\n public shouldComponentUpdate(nextProps: IRefineItemProps, nextState: IRefineItemState): boolean {\r\n if (this.state === nextState && this.props === nextProps) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n public render(): JSX.Element | undefined {\r\n const {\r\n isDisabled,\r\n refineItemCommonProps,\r\n parentProductRefinerHierarchy,\r\n productRefinerValue,\r\n selectedRefinementCriterion,\r\n productCountAriaLabel,\r\n singleProductCountAriaLabel,\r\n index,\r\n children,\r\n onToggle,\r\n context,\r\n telemetryContent,\r\n refineItemAriaLabel,\r\n refineItemsAriaLabel,\r\n yesText,\r\n noText,\r\n transitRefinerRecordId,\r\n ...attrs\r\n } = this.props;\r\n if (!productRefinerValue) {\r\n refineItemCommonProps.telemetry.error('[refine-item] Cannot render refineItem without productRefinerValue');\r\n return undefined;\r\n }\r\n if (!productRefinerValue.LeftValueBoundString) {\r\n refineItemCommonProps.telemetry.warning(\r\n `[refine-item] RefineItem without LeftValueBoundString: ${JSON.stringify(productRefinerValue)}`\r\n );\r\n }\r\n const isSingleSelect = parentProductRefinerHierarchy.RefinerTypeValue === RefinerType.SingleSelect;\r\n let itemTypeClassName = isSingleSelect ? 'single-select' : 'multi-select';\r\n itemTypeClassName = `ms-refine-submenu-item ${itemTypeClassName}`;\r\n const inputType = isSingleSelect ? 'radio' : 'checkbox';\r\n const isChecked = !!selectedRefinementCriterion;\r\n itemTypeClassName = isChecked ? `${itemTypeClassName}-checked` : itemTypeClassName;\r\n if (parentProductRefinerHierarchy.SourceValue === ProductRefinerSource.Rating) {\r\n return this._renderRating(\r\n productRefinerValue,\r\n parentProductRefinerHierarchy,\r\n isChecked,\r\n context,\r\n index,\r\n telemetryContent,\r\n productCountAriaLabel,\r\n singleProductCountAriaLabel\r\n );\r\n }\r\n let labelText = productRefinerValue.LeftValueBoundLocalizedString || productRefinerValue.LeftValueBoundString;\r\n\r\n if (transitRefinerRecordId && productRefinerValue.RefinerRecordId === Number(transitRefinerRecordId)) {\r\n if (labelText === '0') {\r\n labelText = noText ?? 'No';\r\n } else if (labelText === '1') {\r\n labelText = yesText ?? 'Yes';\r\n }\r\n }\r\n\r\n if (parentProductRefinerHierarchy.KeyName === 'Sperret for Svalbard') {\r\n if (labelText === '0') {\r\n labelText = noText ?? 'No';\r\n } else if (labelText === '1') {\r\n labelText = yesText ?? 'Yes';\r\n }\r\n }\r\n\r\n this.payLoad.contentAction.etext = labelText;\r\n const attribute = getTelemetryAttributes(telemetryContent!, this.payLoad);\r\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Replace with actual value for empty string.\r\n const productText = labelText || '';\r\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Replace with actual value for empty string.\r\n const productCount = productRefinerValue.Count || 0;\r\n let refineMenuItemAriaLabel;\r\n if (productCount === 1) {\r\n refineMenuItemAriaLabel = refineItemAriaLabel\r\n ? format(refineItemAriaLabel, parentProductRefinerHierarchy.KeyName, productText)\r\n : '';\r\n } else {\r\n refineMenuItemAriaLabel = refineItemsAriaLabel\r\n ? format(refineItemsAriaLabel, parentProductRefinerHierarchy.KeyName, productText, productCount)\r\n : '';\r\n }\r\n\r\n const dimensionType = (this.props.parentProductRefinerHierarchy.KeyName?.toLocaleLowerCase() ?? '') as DimensionTypes;\r\n const shouldDisplayAsSwatch = this._getShouldDisplayAsSwatch(dimensionType);\r\n\r\n let className = 'ms-refine-submenu-item';\r\n if (shouldDisplayAsSwatch) {\r\n className = classnames(className, `ms-refine-submenu-item__dimension__${dimensionType}`);\r\n }\r\n\r\n // If the swatch has no color or image specified, it should be displayed as text.\r\n // We don't use swatch logic to display the number of the results found together with the text.\r\n const hasColor = !StringExtensions.isNullOrWhitespace(productRefinerValue.SwatchColorHexCode);\r\n const hasImage = !StringExtensions.isNullOrWhitespace(productRefinerValue.SwatchImageUrl);\r\n const hasContentSwatch = hasColor || hasImage;\r\n const tooltip = `${labelText}${productRefinerValue.Count !== undefined ? ` (${productRefinerValue.Count})` : ''}`;\r\n\r\n return (\r\n
  • \r\n \r\n {hasContentSwatch && shouldDisplayAsSwatch && this._renderSwatch(dimensionType)}\r\n \r\n \r\n
  • \r\n );\r\n }\r\n\r\n private _getShouldDisplayAsSwatch(dimensionType: DimensionTypes) {\r\n const shouldDisplayAsSwatch = checkIfShouldDisplayAsSwatch(dimensionType, this.props.context as ICoreContext);\r\n return shouldDisplayAsSwatch;\r\n }\r\n\r\n private _renderSwatch(dimensionType: DimensionTypes): JSX.Element | null {\r\n const productRefinerValue = this.props.productRefinerValue;\r\n\r\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Replace with actual value for empty string.\r\n const text = productRefinerValue.LeftValueBoundLocalizedString || productRefinerValue.LeftValueBoundString || '';\r\n const swatchItems = [\r\n {\r\n itemId: `${productRefinerValue.RefinerRecordId ?? ''}-${dimensionType}-${text}`,\r\n value: text,\r\n dimensionType,\r\n colorHexCode: productRefinerValue.SwatchColorHexCode,\r\n imageUrl: productRefinerValue.SwatchImageUrl\r\n }\r\n ];\r\n\r\n return (\r\n \r\n );\r\n }\r\n\r\n private _getRefinerUrl(): string {\r\n const { urlBuilder, parentProductRefinerHierarchy, productRefinerValue, selectedRefinementCriterion } = this.props;\r\n\r\n if (productRefinerValue) {\r\n return urlBuilder({\r\n parentProductRefinerHierarchy,\r\n productRefinerValue,\r\n isSelecting: !selectedRefinementCriterion\r\n });\r\n }\r\n\r\n return '';\r\n }\r\n\r\n private readonly _onClick = (e: React.MouseEvent): void => {\r\n e.preventDefault();\r\n\r\n const { parentProductRefinerHierarchy, productRefinerValue, selectedRefinementCriterion } = this.props;\r\n if (productRefinerValue) {\r\n this.props.onToggle({\r\n parentProductRefinerHierarchy,\r\n productRefinerValue,\r\n isSelecting: !selectedRefinementCriterion\r\n });\r\n\r\n setTimeout(() => {\r\n this.anchorType.current && this.anchorType.current.focus();\r\n }, 0);\r\n }\r\n };\r\n\r\n private _renderRating(\r\n productRefinerValue: ProductRefinerValue,\r\n parentProductRefinerHierarchy: IProductRefinerHierarchy,\r\n isChecked: boolean,\r\n context: ICoreContext,\r\n index?: number,\r\n telemetryContent?: ITelemetryContent,\r\n ratingUserCountAriaLabel?: string,\r\n ratingSingleUserCountAriaLabel?: string\r\n ): JSX.Element | undefined {\r\n if (productRefinerValue.LeftValueBoundString) {\r\n this.payLoad.contentAction.etext = productRefinerValue.LeftValueBoundLocalizedString;\r\n const attribute = getTelemetryAttributes(telemetryContent!, this.payLoad);\r\n const refinerRating = Number.parseInt(productRefinerValue.LeftValueBoundString, 10);\r\n const ratingRefiner = this.props.selectedRefinerValues?.find(\r\n value => value.DataTypeValue === productRefinerValue.DataTypeValue\r\n );\r\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Replace with actual value for empty string.\r\n const selectedRating = Number.parseInt(ratingRefiner?.LeftValueBoundString || '0', 10);\r\n const defaultChkProductCount = 1;\r\n let ratingComponentClass: string = 'ms-rating-component';\r\n if (refinerRating > selectedRating) {\r\n ratingComponentClass = `${ratingComponentClass}__up`;\r\n } else if (refinerRating < selectedRating) {\r\n ratingComponentClass = `${ratingComponentClass}__down`;\r\n } else {\r\n ratingComponentClass = `${ratingComponentClass}__current`;\r\n }\r\n const productCountAriaLabelValue =\r\n productRefinerValue.Count !== undefined && productRefinerValue.Count === defaultChkProductCount\r\n ? ratingSingleUserCountAriaLabel && format(ratingSingleUserCountAriaLabel, productRefinerValue.Count)\r\n : ratingUserCountAriaLabel && format(ratingUserCountAriaLabel, productRefinerValue.Count);\r\n return (\r\n \r\n \r\n \r\n \r\n {productRefinerValue.Count !== undefined && `(${productRefinerValue.Count})`}\r\n \r\n \r\n \r\n );\r\n }\r\n return undefined;\r\n }\r\n}\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { IProductRefinerHierarchy } from '@msdyn365-commerce/commerce-entities';\r\nimport { IAny, ICoreContext, IGeneric } from '@msdyn365-commerce/core';\r\nimport { DisplayTemplate, ProductRefinerSource, ProductRefinerValue, RefinerType } from '@msdyn365-commerce/retail-proxy';\r\nimport { Button, Collapse, ITelemetryContent } from '@msdyn365-commerce-modules/utilities';\r\nimport classnames from 'classnames';\r\nimport * as React from 'react';\r\n\r\nimport RangeRefineItem, { RangeRefineItemType } from './range-refine-item';\r\nimport RefineItem from './refine-item';\r\nimport { IRefineItemCommonProps } from './refine-item.props.common';\r\nimport { IRefineItemToggleNotification } from './refine-item-toggle-notification';\r\nimport { findMatchingRefinementCriterion, isRangeType } from './utilities';\r\n\r\n/**\r\n * Properties associated with the RefineSubmenu component.\r\n */\r\nexport interface IRefineSubmenuProps {\r\n tempRangeTypeTODO: RangeRefineItemType;\r\n minValueSliderThumbAriaLabel?: string;\r\n maxValueSliderThumbAriaLabel?: string;\r\n productRefinerHierarchy: IProductRefinerHierarchy;\r\n selectedRefinerValues: ProductRefinerValue[];\r\n refineItemCommonProps: IRefineItemCommonProps;\r\n isDisabled: boolean;\r\n isExpandedOnInitialLoad: boolean;\r\n context: ICoreContext>;\r\n moduleId: string;\r\n moduleTypeName: string;\r\n productCountAriaLabel?: string;\r\n singleProductCountAriaLabel?: string;\r\n refineItemAriaLabel?: string;\r\n refineItemsAriaLabel?: string;\r\n isMobile?: boolean;\r\n yesText?: string;\r\n noText?: string;\r\n transitRefinerRecordId?: string;\r\n\r\n /**\r\n * The telemetry content\r\n */\r\n telemetryContent?: ITelemetryContent;\r\n onUpdateRefiners(notfication: Readonly): void;\r\n urlBuilder(refiner: IRefineItemToggleNotification): string;\r\n}\r\n\r\n/**\r\n * Refine submenu state.\r\n */\r\nexport interface IRefineSubmenuState extends React.ComponentState {\r\n expanded: boolean;\r\n}\r\n\r\n/**\r\n *\r\n * The RefineSubmenu component renders the submenu category and child items.\r\n * This computed observes the stateful category hierarchy object.\r\n * @extends {React.PureComponent}\r\n */\r\nclass RefineSubmenu extends React.Component {\r\n private readonly MaxItems = 16;\r\n\r\n constructor(props: IRefineSubmenuProps) {\r\n super(props);\r\n\r\n this._onToggleItem = this._onToggleItem.bind(this);\r\n this._onToggleSubmenu = this._onToggleSubmenu.bind(this);\r\n\r\n const isExpanded = this.props.isExpandedOnInitialLoad;\r\n\r\n // If (this.props.productRefinerHierarchy.DataTypeValue === ProductRefinerValueDataTypeValue.Range) {\r\n // isExpanded = true;\r\n // }\r\n\r\n this.state = {\r\n expanded: isExpanded,\r\n isShowFullList: props.productRefinerHierarchy.Values.length <= this.MaxItems\r\n };\r\n }\r\n\r\n public shouldComponentUpdate(nextProps: IRefineSubmenuProps, nextState: IRefineSubmenuState): boolean {\r\n if (this.state === nextState && this.props === nextProps) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n public render(): JSX.Element | null {\r\n const { productRefinerHierarchy, refineItemCommonProps } = this.props;\r\n\r\n if (!productRefinerHierarchy) {\r\n refineItemCommonProps.telemetry.error('Cannot render submenu without refiner hierarchy data');\r\n }\r\n\r\n if (productRefinerHierarchy.SourceValue === ProductRefinerSource.Rating && this.props.context.app.config.hideRating) {\r\n return null;\r\n }\r\n\r\n const className = classnames(\r\n 'ms-refine-submenu',\r\n 'list-group',\r\n productRefinerHierarchy.KeyName // Deprecated because of the localization issues. Leaving for backward compatibility reasons.\r\n );\r\n\r\n return (\r\n
    \r\n \r\n {productRefinerHierarchy.KeyName}\r\n \r\n {\r\n // Simulate the 'resize' event so that sliders gets rendered correctly.\r\n // If not end Slider will always start a position 0 since hidden elements have no width.\r\n window.dispatchEvent(new Event('resize'));\r\n }}>\r\n {this._renderChildItems(productRefinerHierarchy)}\r\n \r\n
    \r\n );\r\n }\r\n\r\n private _renderChildItems(productRefinerHierarchy: IProductRefinerHierarchy): JSX.Element | null {\r\n if (isRangeType(productRefinerHierarchy.DataTypeValue)) {\r\n return this._renderRange(productRefinerHierarchy);\r\n }\r\n return this._renderSingleMultiSelect(productRefinerHierarchy);\r\n }\r\n\r\n private _renderSingleMultiSelect(productRefinerHierarchy: IProductRefinerHierarchy): JSX.Element | null {\r\n const {\r\n isDisabled,\r\n refineItemCommonProps,\r\n selectedRefinerValues,\r\n context,\r\n productCountAriaLabel,\r\n singleProductCountAriaLabel,\r\n refineItemAriaLabel,\r\n refineItemsAriaLabel,\r\n isMobile\r\n } = this.props;\r\n const isSingleSelect =\r\n productRefinerHierarchy.RefinerTypeValue === RefinerType.SingleSelect &&\r\n productRefinerHierarchy.SourceValue === ProductRefinerSource.Rating;\r\n const role = isSingleSelect ? { role: 'listbox' } : undefined;\r\n const refinerValuesList = productRefinerHierarchy.Values || [];\r\n refinerValuesList.sort(\r\n (a, b) => (a.LeftValueBoundLocalizedString || a.LeftValueBoundString || '').localeCompare(b.LeftValueBoundLocalizedString || b.LeftValueBoundString || '', context.request.locale)\r\n );\r\n const listItems = refinerValuesList.map((child: ProductRefinerValue, index: number) => {\r\n if (!child) {\r\n refineItemCommonProps.telemetry.error(\r\n `[refine-submenu] Could not render refine item for refiner ${productRefinerHierarchy.RecordId} (${productRefinerHierarchy.KeyName})`\r\n );\r\n return null;\r\n }\r\n if (index > (this.MaxItems - 1) && !this.state.isShowFullList) {\r\n return null;\r\n }\r\n const selectedRefinementCriterion = findMatchingRefinementCriterion(child, selectedRefinerValues);\r\n\r\n return (\r\n \r\n refinerValuesList.find(value => value.RefinerRecordId === selectedValue.RefinerRecordId)\r\n )}\r\n refineItemCommonProps={refineItemCommonProps}\r\n onToggle={this._onToggleItem}\r\n urlBuilder={this.props.urlBuilder}\r\n isDisabled={isDisabled}\r\n key={index}\r\n index={index}\r\n context={context}\r\n moduleId={this.props.moduleId}\r\n moduleTypeName={this.props.moduleTypeName}\r\n telemetryContent={this.props.telemetryContent}\r\n productCountAriaLabel={productCountAriaLabel}\r\n refineItemAriaLabel={refineItemAriaLabel}\r\n refineItemsAriaLabel={refineItemsAriaLabel}\r\n singleProductCountAriaLabel={singleProductCountAriaLabel}\r\n isMobileView={isMobile}\r\n yesText={this.props.yesText}\r\n noText={this.props.noText}\r\n transitRefinerRecordId={this.props.transitRefinerRecordId}\r\n />\r\n );\r\n });\r\n return (\r\n \r\n {listItems}\r\n {refinerValuesList.length > this.MaxItems && }\r\n \r\n );\r\n }\r\n\r\n private _getRangeType(productRefinerHierarchy: IProductRefinerHierarchy): 'input' | 'slider' {\r\n if (\r\n productRefinerHierarchy.DisplayTemplateValue === DisplayTemplate.Range ||\r\n productRefinerHierarchy.DisplayTemplateValue === DisplayTemplate.Slider ||\r\n productRefinerHierarchy.DisplayTemplateValue === DisplayTemplate.SliderWithBars\r\n ) {\r\n return 'slider';\r\n }\r\n return 'input';\r\n }\r\n\r\n private _renderRange(productRefinerHierarchy: IProductRefinerHierarchy): JSX.Element | null {\r\n const {\r\n isDisabled,\r\n refineItemCommonProps,\r\n selectedRefinerValues,\r\n context,\r\n minValueSliderThumbAriaLabel,\r\n maxValueSliderThumbAriaLabel\r\n } = this.props;\r\n const submenuClassNamePrefix = 'ms-refine-submenu__item list-group-item refine-submenu__item';\r\n const refinerValuesList = productRefinerHierarchy.Values || [];\r\n const listItems = refinerValuesList.map((child: ProductRefinerValue, index: number) => {\r\n if (!child) {\r\n refineItemCommonProps.telemetry.error(\r\n `Could not render refine item for refiner ${productRefinerHierarchy.RecordId} (${productRefinerHierarchy.KeyName})`\r\n );\r\n return null;\r\n }\r\n\r\n const selectedRefinementCriterion = findMatchingRefinementCriterion(child, selectedRefinerValues);\r\n\r\n const rangeType = this._getRangeType(productRefinerHierarchy);\r\n const key = selectedRefinementCriterion\r\n ? `${selectedRefinementCriterion.LeftValueBoundString}-${selectedRefinementCriterion.RightValueBoundString}`\r\n : `not-selected-${index}`;\r\n return (\r\n
  • \r\n \r\n
  • \r\n );\r\n });\r\n return
      {listItems}
    ;\r\n }\r\n\r\n private _onToggleItem(itemToggleNotification: IRefineItemToggleNotification): void {\r\n this.props.onUpdateRefiners(itemToggleNotification);\r\n }\r\n\r\n private _onToggleSubmenu(): void {\r\n this.setState(prevState => ({\r\n expanded: !prevState.expanded\r\n }));\r\n }\r\n}\r\n\r\nexport default RefineSubmenu;\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { ITelemetry } from '@msdyn365-commerce/core';\r\nimport { AttributeDataType, DisplayTemplate, ProductRefinerValue, RefinerType } from '@msdyn365-commerce/retail-proxy';\r\n\r\nimport { IProductRefinerHierarchy } from '@msdyn365-commerce/commerce-entities';\r\nimport { DimensionTypes } from '@msdyn365-commerce-modules/retail-actions';\r\nimport { IRefineItemToggleNotification } from './refine-item-toggle-notification';\r\n\r\n/**\r\n * Types of product refiner values.\r\n * @deprecated This will be removed soon. Please, use `AttributeDataType` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { AttributeDataType } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\nexport enum ProductRefinerValueDataTypeValue {\r\n /**\r\n * Range slider is used for selections like price.\r\n * @deprecated This will be removed soon. Please, use `AttributeDataType` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { AttributeDataType } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\n Range = 1,\r\n\r\n /**\r\n * Range input is a different way to specify ranges and can be expressed with input boxes\r\n * as well as a set of discrete single-select type values.\r\n * @deprecated This will be removed soon. Please, use `AttributeDataType` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { AttributeDataType } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\n RangeInput = 4,\r\n\r\n /**\r\n * This is a discrete list item, either multi-select or single-select.\r\n * @deprecated This will be removed soon. Please, use `AttributeDataType` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { AttributeDataType } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\n List = 5,\r\n\r\n /**\r\n * Boolean types allows only single-select.\r\n * @deprecated This will be removed soon. Please, use `AttributeDataType` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { AttributeDataType } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\n Boolean = 6\r\n}\r\n\r\n/**\r\n * Types of product refiners.\r\n * @deprecated This will be removed soon. Please, use `RefinerType` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { RefinerType } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\nexport enum ProductRefinerTypeValue {\r\n /**\r\n * Refiner values are single-select.\r\n * @deprecated This will be removed soon. Please, use `RefinerType` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { RefinerType } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\n Single = 0,\r\n\r\n /**\r\n * Refiner values are multi-select.\r\n * @deprecated This will be removed soon. Please, use `RefinerType` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { RefinerType } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\n Multi = 1\r\n}\r\n\r\n/**\r\n * ProductRefinerSource enum type.\r\n * @deprecated This will be removed soon. Please, use `ProductRefinerSource` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { ProductRefinerSource } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\nexport enum ProductRefinerSource {\r\n /**\r\n * The None member.\r\n * @deprecated This will be removed soon. Please, use `ProductRefinerSource` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { ProductRefinerSource } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\n None = 0,\r\n\r\n /**\r\n * The Attribute member.\r\n * @deprecated This will be removed soon. Please, use `ProductRefinerSource` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { ProductRefinerSource } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\n Attribute = 1,\r\n\r\n /**\r\n * The Category member.\r\n * @deprecated This will be removed soon. Please, use `ProductRefinerSource` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { ProductRefinerSource } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\n Category = 2,\r\n\r\n /**\r\n * The Price member.\r\n * @deprecated This will be removed soon. Please, use `ProductRefinerSource` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { ProductRefinerSource } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\n Price = 3,\r\n\r\n /**\r\n * The Rating member.\r\n * @deprecated This will be removed soon. Please, use `ProductRefinerSource` from `@msdyn365-commerce/retail-proxy` instead.\r\n * @example\r\n * ```\r\n * import { ProductRefinerSource } from `@msdyn365-commerce/retail-proxy`;\r\n * ```\r\n */\r\n Rating = 4\r\n}\r\n\r\nexport interface IRefineItemData {\r\n sourceValue?: number;\r\n swatchImageUrl?: string;\r\n swatchColorHexCode?: string;\r\n refinerItemId: number;\r\n dataTypeValue?: number;\r\n name: string;\r\n label: string;\r\n count?: number;\r\n isChecked: boolean;\r\n refineItemUrl?: string;\r\n minValue?: string;\r\n maxValue?: string;\r\n dimensionType?: DimensionTypes;\r\n rowNumber?: number;\r\n unitText?: string;\r\n updatedSliderMaxValue?: string;\r\n updatedSliderMinValue?: string;\r\n}\r\n/**\r\n * Checks if the data type value corresponds to a slider.\r\n * @param dataTypeValue\r\n */\r\nexport function isRangeType(dataTypeValue: number | undefined): boolean {\r\n return dataTypeValue === AttributeDataType.Currency || dataTypeValue === AttributeDataType.Decimal;\r\n}\r\n\r\n/**\r\n * Checks if the data type value corresponds to a range type integer.\r\n * @param dataTypeValue\r\n */\r\nexport function isRangeTypeForInteger(dataTypeValue: number | undefined): boolean {\r\n return (\r\n dataTypeValue === AttributeDataType.Currency ||\r\n dataTypeValue === AttributeDataType.Decimal ||\r\n dataTypeValue === AttributeDataType.Integer\r\n );\r\n}\r\n\r\n/**\r\n * Checks if the data type value corresponds to a boolean.\r\n * @param dataTypeValue\r\n */\r\nexport function isBoolean(dataTypeValue: number | undefined): boolean {\r\n return (\r\n dataTypeValue === AttributeDataType.TrueFalse);\r\n}\r\n\r\n/**\r\n * Checks if the data type value corresponds to a custom input box Range.\r\n * @param dataTypeValue\r\n */\r\nexport function isCustomRangeTypeIntegerSelected(\r\n selectedRefinementCriterion: ProductRefinerValue,\r\n parentProductRefinerHierarchy: IProductRefinerHierarchy\r\n): boolean {\r\n return (\r\n selectedRefinementCriterion?.RowNumber !== undefined &&\r\n selectedRefinementCriterion?.RowNumber !== null &&\r\n selectedRefinementCriterion?.DataTypeValue === AttributeDataType.Integer &&\r\n parentProductRefinerHierarchy.DisplayTemplateValue === DisplayTemplate.Range\r\n );\r\n}\r\n\r\n/**\r\n * Checks if the selectedRefinementCriterion is siingle type with API va;ues or custom type.\r\n * If custom type then RowNumber is null\r\n * @param dataTypeValue\r\n */\r\nexport function isSingleSelectRangeTypeIntegerSelected(\r\n selectedRefinementCriterion: ProductRefinerValue,\r\n productRefinerValue: ProductRefinerValue\r\n): boolean {\r\n return (\r\n productRefinerValue.LeftValueBoundString === selectedRefinementCriterion?.LeftValueBoundString &&\r\n productRefinerValue.RightValueBoundString === selectedRefinementCriterion?.RightValueBoundString &&\r\n selectedRefinementCriterion?.RowNumber !== undefined &&\r\n selectedRefinementCriterion?.RowNumber !== null &&\r\n selectedRefinementCriterion !== undefined\r\n );\r\n}\r\n\r\n/**\r\n * Find the refinement criterion associated with this product refiner value.\r\n * @param productRefinerValue Product refiner value to match.\r\n * @param refinementCriteria Selected refinement criteria.\r\n */\r\nexport function findMatchingRefinementCriterion(\r\n productRefinerValue: ProductRefinerValue,\r\n refinementCriteria: ProductRefinerValue[]\r\n): ProductRefinerValue | undefined {\r\n // If the value is a range, then match only on data type value; otherwise match on item string\r\n return refinementCriteria.find((refinementCriterion: ProductRefinerValue) =>\r\n isMatchingRefinementCriterion(productRefinerValue, refinementCriterion)\r\n );\r\n}\r\n\r\n/**\r\n * Find the refinement criterion associated with this product refiner value.\r\n * @param productRefinerValue Product refiner value to match.\r\n * @param refinementCriteria Selected refinement criteria.\r\n * @param refinementCriterion\r\n */\r\nexport function isMatchingRefinementCriterion(\r\n productRefinerValue: ProductRefinerValue,\r\n refinementCriterion: ProductRefinerValue,\r\n parent?: IProductRefinerHierarchy\r\n): boolean {\r\n // If the value is a range, then match only on data type value; otherwise match on item string\r\n // Distinguish by displaytype also\r\n return (\r\n refinementCriterion.RefinerRecordId === productRefinerValue.RefinerRecordId &&\r\n refinementCriterion.RefinerSourceValue === productRefinerValue.RefinerSourceValue &&\r\n refinementCriterion.DataTypeValue === productRefinerValue.DataTypeValue &&\r\n ((parent?.DisplayTemplateValue === DisplayTemplate.Range\r\n ? isRangeType(refinementCriterion.DataTypeValue)\r\n : isRangeTypeForInteger(refinementCriterion.DataTypeValue)) ||\r\n refinementCriterion.LeftValueBoundString === productRefinerValue.LeftValueBoundString)\r\n );\r\n}\r\n\r\nexport function getIntegerRangeName(productRefinerValue: ProductRefinerValue): string {\r\n let rangeValue = '';\r\n\r\n if (productRefinerValue.LeftValueBoundString === '' && productRefinerValue.RightValueBoundString !== '') {\r\n rangeValue = `< ${productRefinerValue.RightValueBoundLocalizedString || productRefinerValue.RightValueBoundString}`;\r\n } else if (productRefinerValue.RightValueBoundString === '' && productRefinerValue.LeftValueBoundString !== '') {\r\n rangeValue = `> ${productRefinerValue.LeftValueBoundLocalizedString || productRefinerValue.LeftValueBoundString}`;\r\n } else if (productRefinerValue.RightValueBoundString !== '' && productRefinerValue.LeftValueBoundString !== '') {\r\n rangeValue = `${productRefinerValue.LeftValueBoundLocalizedString ||\r\n productRefinerValue.LeftValueBoundString} - ${productRefinerValue.RightValueBoundString ||\r\n productRefinerValue.RightValueBoundString}`;\r\n }\r\n return rangeValue;\r\n}\r\n\r\n/**\r\n * Get input without formatting.\r\n * @param input - Input string.\r\n * @returns - Returns number.\r\n */\r\nexport function getInputWithoutFormatting(input: string): string {\r\n // First try to cast raw input to a number\r\n const inputAsNumber = Number(input);\r\n if (!Number.isNaN(inputAsNumber)) {\r\n return input;\r\n }\r\n\r\n // Otherwise try a reverse lookup and fall back to the raw input if all else fails\r\n // const reverseLookupResult = formattedPriceReverseLookup.get(input);\r\n // return reverseLookupResult || input;\r\n return input;\r\n}\r\n\r\nexport function getUpdatedRefinementCriteria(\r\n itemToggleNotification: IRefineItemToggleNotification,\r\n currentRefinementCriteria: ProductRefinerValue[]\r\n): ProductRefinerValue[] {\r\n const updatedRefinementCriteria: ProductRefinerValue[] = [];\r\n let toggledItemFound = false;\r\n\r\n // Keeping only itemToggled value for integer-range type in currentRefinementCriteria\r\n if (\r\n itemToggleNotification.parentProductRefinerHierarchy.DataTypeValue === AttributeDataType.Integer &&\r\n itemToggleNotification.parentProductRefinerHierarchy.DisplayTemplateValue === DisplayTemplate.Range\r\n ) {\r\n currentRefinementCriteria = currentRefinementCriteria.filter(r => {\r\n return r.RefinerRecordId !== itemToggleNotification.productRefinerValue.RefinerRecordId;\r\n });\r\n }\r\n\r\n currentRefinementCriteria.forEach((selectedCriterion: ProductRefinerValue) => {\r\n if (\r\n isMatchingRefinementCriterion(\r\n itemToggleNotification.productRefinerValue,\r\n selectedCriterion,\r\n itemToggleNotification.parentProductRefinerHierarchy\r\n )\r\n ) {\r\n toggledItemFound = true;\r\n if (itemToggleNotification.isSelecting) {\r\n const next = {\r\n ...selectedCriterion,\r\n LeftValueBoundString:\r\n (itemToggleNotification.rangeStart !== undefined && `${itemToggleNotification.rangeStart}`) ||\r\n selectedCriterion.LeftValueBoundString,\r\n RightValueBoundString:\r\n (itemToggleNotification.rangeEnd !== undefined && `${itemToggleNotification.rangeEnd}`) ||\r\n selectedCriterion.RightValueBoundString\r\n };\r\n updatedRefinementCriteria.push(next);\r\n } // Else the item is being de-selected, so omit it from the refinement criteria\r\n } else {\r\n // Keep existing criterion because it is not in the item toggle notification\r\n updatedRefinementCriteria.push(selectedCriterion);\r\n }\r\n });\r\n\r\n if (!toggledItemFound) {\r\n const next = {\r\n ...itemToggleNotification.productRefinerValue,\r\n LeftValueBoundString:\r\n (itemToggleNotification.rangeStart !== undefined && `${itemToggleNotification.rangeStart}`) ||\r\n itemToggleNotification.productRefinerValue.LeftValueBoundString,\r\n RightValueBoundString:\r\n (itemToggleNotification.rangeEnd !== undefined && `${itemToggleNotification.rangeEnd}`) ||\r\n itemToggleNotification.productRefinerValue.RightValueBoundString\r\n };\r\n updatedRefinementCriteria.push(next);\r\n\r\n // If single select, then deselect any others in the parent refiner group\r\n if (\r\n (itemToggleNotification.productRefinerValue.DataTypeValue === AttributeDataType.Text ||\r\n itemToggleNotification.productRefinerValue.DataTypeValue === AttributeDataType.TrueFalse) &&\r\n itemToggleNotification.parentProductRefinerHierarchy.RefinerTypeValue === RefinerType.SingleSelect\r\n ) {\r\n itemToggleNotification.parentProductRefinerHierarchy.Values.forEach((child: ProductRefinerValue) => {\r\n if (child.RefinerRecordId === next.RefinerRecordId && child.LeftValueBoundString === next.LeftValueBoundString) {\r\n // Do nothing\r\n } else {\r\n const matchingIndex = updatedRefinementCriteria.findIndex((criterion: ProductRefinerValue) =>\r\n isMatchingRefinementCriterion(child, criterion, itemToggleNotification.parentProductRefinerHierarchy)\r\n );\r\n if (matchingIndex > -1) {\r\n updatedRefinementCriteria.splice(matchingIndex, 1);\r\n }\r\n }\r\n });\r\n }\r\n }\r\n\r\n return updatedRefinementCriteria;\r\n}\r\n\r\nexport function formatPrice(\r\n amount: string | undefined,\r\n currency: string | undefined,\r\n locale: string | undefined,\r\n telemetry: ITelemetry\r\n): string {\r\n if (!amount || !currency) {\r\n telemetry.trace(`[refine-menu.utilities.formatPrice] could not format price for ${amount} ${currency}`);\r\n return amount || '';\r\n }\r\n const priceAmount = (amount && Number(amount)) || 0;\r\n let result: string;\r\n\r\n try {\r\n result = new Intl.NumberFormat(locale, {\r\n style: 'currency',\r\n currencyDisplay: 'symbol',\r\n currency,\r\n minimumFractionDigits: 0\r\n }).format(priceAmount);\r\n } catch (error) {\r\n result = `${priceAmount} ${currency}`;\r\n telemetry.warning(`[refine-menu.utilities.formatPrice] Failed to format price for ${result}: ${error}`);\r\n }\r\n\r\n return result;\r\n}\r\n","import { ICoreContext } from '@msdyn365-commerce/core';\r\nimport { ProductSearchResultExt } from \"../../modules/dlvry-search-result-container/components\";\r\nimport { Customer } from '@msdyn365-commerce/retail-proxy';\r\nimport { hasAccessToBuy } from '.';\r\n\r\nexport interface OnBuyHasAccessValidatorResult {\r\n isValid: boolean;\r\n message?: string;\r\n}\r\n\r\nexport async function onBuyHasAccessValidator(\r\n context: ICoreContext,\r\n customer: Customer | undefined,\r\n product: ProductSearchResultExt,\r\n validationMessage: string | undefined\r\n): Promise {\r\n if (!product || !product.AttributeValues) {\r\n return { isValid: true };\r\n }\r\n\r\n const hasAccess = hasAccessToBuy(context, customer, product.AttributeValues);\r\n\r\n return {\r\n isValid: hasAccess,\r\n message: hasAccess ? undefined : validationMessage\r\n };\r\n}\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\nimport { ICookieValue, ICookieContext } from '@msdyn365-commerce/core';\r\n\r\nexport const GetCookie = (cookies: ICookieContext, cookieName: string): string | undefined => {\r\n const marketCookie = cookies.get(cookieName) as ICookieValue | undefined;\r\n\r\n if (marketCookie && marketCookie.value && marketCookie.value.length > 0) {\r\n return marketCookie.value;\r\n } else {\r\n return undefined;\r\n }\r\n};\r\n\r\nexport const SetCookie = (cookies: ICookieContext, value: string, cookieName: string, exp: number): void => {\r\n if (value) {\r\n cookies.set(cookieName, value, { path: '/', maxAge: exp });\r\n }\r\n};\r\n"],"names":["GetOrganizationCustomerInput","constructor","apiSettings","user","getDataServiceRequest","this","query","createDataServiceRequestForOperation","Entities","bypassCache","returnEntity","shouldCacheOutput","getCacheKey","getCacheObjectType","dataCacheType","DataServiceQuery","getOrganizationCustomerAction","async","input","ctx","requestContext","isAuthenticated","callActionOrExecute","getOrganizationCustomer","createObservableDataAction","id","action","inputData","_user$customerAccount","customerAccountNumber","getProductUnitOfMeasureOptionsInput","queryResultSettings","productIds","resultSettings","top","getProductUnitOfMeasureOptionsAsync","context","request","callerContext","BaseCollectionInput","pageType","refiners","category","searchText","includeAttributes","isUpdateRefinerPanel","locale","catalogId","channelInventoryConfiguration","inventoryRefiner","_objectSpread","Paging","toJS","Sorting","generateCacheKey","key","value","map","refiner","RefinerRecordId","LeftValueBoundString","RightValueBoundString","convertToString","createBaseCollectionInput","args","inputClassConstuctor","urlTokens","categoryId","QueryResultSettingsProxy","fromInputData","QueryResultSettings","queryRefiners","hydrateRefinersFromUrl","config","undefined","_inputData$config","updateRefinerPanel","getUpdateRefinerPanel","getCatalogId","_args$requestContext$","sorting","Columns","JSON","parse","decodeURIComponent","itemId","q","recommendation","productId","stringify","ProductId","Recommendation","SearchText","discountIds","DiscountIds","Error","CachedPriceForProductSearchResultInput","products","productRecIds","ArrayExtensions","hasElements","Promise","resolve","product","RecordId","projectDomain","ChannelId","channelId","CatalogId","productPrices","getActivePricesAsync","getPagingFromInputDataOrDefaultValue","Date","productResults","activePrice","find","price","_activePrice$Customer","_activePrice$BasePric","_activePrice$TradeAgr","_activePrice$Adjusted","Badge","getDiscountBadge","Price","CustomerContextualPrice","BasePrice","Math","max","TradeAgreementPrice","AdjustedPrice","ProductPrice","PrefetchedPrice","error","telemetry","exception","debug","GetFullProductsByCollectionInput","length","ProductListInventoryFilteringOptions","returnProducts","productSearchResults","metadataCount","productSearchResultsWithImages","productSearchResult","newImageUrl","generateProductImageUrl","PrimaryImageUrl","app","inventoryLevel","InventoryLevels","threshold","enableStockCheck","count","AttributeValues","element","InventoryProductAttributeRecordId","inventoryRanges","TextValue","InventoryOutOfStockAttributeValueText","channelInventoryConfigurationId","inventoryAwareSortableAttributeId","ProductAvailabilitySortableAttributeRecordId","actionDataAction","_context$requestConte","_context$requestConte2","_context$requestConte3","_context$requestConte4","_context$requestConte5","_context$requestConte6","promise","channelInventoryConfigurationPromise","searchProductId","searchCriteriaInput","Context","Refinement","slice","IncludeAttributes","SkipVariantExpansion","SearchCondition","index","_input$refiners$index","ExtensionProperties","addOrUpdateZeroPriceRefiner","shouldFilterAlcohol","addAlcoholRefinerAsync","addAllAttributeRefiners","AsyncResult","getInventoryConfigurationAsync","filter","isInStockRefiner","inventoryRefinerValue","getInventorySortableRefinerValue","some","push","productListInventoryDisplay","HideOOS","isInStock","inventoryInStockRefinerValue","prioritySortingAttribute","match","_input$queryResultSet","_input$queryResultSet2","priorityColumnName","column","ColumnName","IsDescending","SortOOS","_input$queryResultSet3","_input$queryResultSet4","sortColumnName","CategoryIds","searchByCriteriaAsync","searchObject","Number","isNaN","RecommendationListId","Ids","_context$requestConte7","accountInformation","getCustomer","GetCustomerInput","split","getProductPromotionsAsync","HeaderContext","CustomerAccountNumber","AccountNumber","LineContexts","p","_p$ProductId","forEach","x","MaxVariantPrice","MinVariantPrice","getCachedPriceForProductSearchResultDataAction","metadata","Top","itemsPerPage","skip","Skip","sortOptions","sortByOptionRelevanceDesc","sortByOptionRatingAsc","sortByOptionRatingDesc","sortByOptionNameAsc","sortByOptionNameDesc","sortByOptionPriceAsc","sortByOptionPriceDesc","sortByOptionBestSelling","sortByOptionNewScore","sortByOptionTrendingScore","MappedSearchInput","buildCacheKey","getMappedSearchConfiguration","getSearchConfigurationAsync","then","searchConfiguration","ProductSortColumns","sortColumn","toUpperCase","warning","Boolean","createInput","getMappedSearchConfigurationDataAction","DefaultValues","RefinersByCollectionInput","getRefinersForCollectionDataAction","alcoholFilter","attributeRefiners","getAllAttributeRefiners","concat","getAlcoholRefiners","defaultRefiners","getProductRefinerHierarchy","defaultCategoryIdValue","defaultProductIdValue","DataTypeValue","AttributeDataType","TrueFalse","UnitText","RowNumber","Count","RefinerSourceValue","ProductRefinerSource","Attribute","_input$channelInvento2","_input$channelInvento3","inventoryProductAttributeRecordId","AlcoholGroupAttributeId","isGodmodeEnabled","godmode","url","requestUrl","searchParams","get","toLowerCase","doAlcoholFiltering","alcoholRefinerRecordId","alcoholGroupAttributeId","result","alcoholRefiner","alcoholLicenseValue","_customer$Attributes","customer","alcoholLicense","Attributes","AttributeValue","StringValue","console","warn","Array","fill","_","toString","addAlcoholRefiner","priceRefiner","channel","Currency","getAttributeRefiners","customerAttributes","attributeRecordId","friendlyName","attributeValue","_customerAttributes$f","attribute","getForsvaretRefiner","forsvaretAttributeId","forsvaretAttributeRecordId","_customerAttributes$f2","IntegerValue","Integer","getSvalbardRefiner","_context$requestConte8","_context$requestConte9","svalbardAttributeId","svalbardAttributeRecordId","blockedSvalbardAttributeId","blockedSvalbardAttributeRecordId","_customerAttributes$f3","addAttributeRefiner","_context$requestConte10","_context$requestConte11","_context$requestConte12","_context$requestConte13","_context$requestConte14","_context$requestConte15","attributeRecordIds","tobaccoRefinerRecordId","cocacolaRefinerRecordId","bamaRefinerRecordId","dutyFreeSugarRefinerRecordId","norturaRefinerRecordId","transitRefiner","transitRefinerRecordId","addAttributeRefinerKeepExisting","forsvaretRefiner","svalbardRefiner","_context$requestConte16","_context$requestConte17","_context$requestConte18","_context$requestConte19","_context$requestConte20","_context$requestConte21","compressedRefinerKeys","compressedRefinerArray","parseQueryParam","compressedRefiner","parsedRefiner","refinerKey","_unused","buildListPageUrl","fullUrl","sortingColumns","skipCount","delete","sortedRefiners","sort","first","second","set","compressedRefiners","compressRefiners","href","getCurrentUrl","MsDyn365","isBrowser","URL","window","location","ChoiceSummary","React","props","super","closeButtonGlyph","_onClick","e","preventDefault","stopPropagation","target","currentTarget","clearAll","getAttribute","includes","selectedRefiner","_getSelectedRefinerChoice","onChoiceClicked","itemClicked","choiceClicked","nextItemToFocus","nextSibling","payLoad","getPayloadObject","telemetryContent","_this$props$context","selectedChoices","refinerHierarchy","choice","parent","hierarchy","Values","isMatchingRefinementCriterion","RefinerValue","_getKeyForRefinerValue","render","clearAllText","label","classNames","choiceAriaLabel","closeAriaLabel","yesLabel","noLabel","items","selectedRefinersMap","contentAction","etext","clearAllAttributes","getTelemetryAttributes","className","classnames","item","isBoolean","Object","assign","urlBuilder","onClick","role","style","fontWeight","LeftValueBoundLocalizedString","productRefinerValue","choiceFormat","choiceRangeValueFormat","refinerValues","overallFormat","rangeFormat","refinerValueName","refinerName","KeyName","isRangeType","replace","_formatPrice","filterValue","amount","currency","trace","cultureFormatter","formatCurrency","selected","__decorate","computed","observer","ErrorMessage","_ref","text","FeatureSearchResultItem","_context$request$app","imageSettings","resources","productName","Name","productRecordId","productUrl","getProductPageUrlSync","actionContext","fallbackImage","getFallbackImageUrl","ItemId","OmniChannelMedia","heading","featureSimilarDescriptionTitle","featureSimilarLooksTitle","onTelemetryClick","gridSettings","imageUrl","altText","img","src","imageProps","fallBackSrc","Image","loadFailureBehavior","renderProductPlacementImage","title","Link","ariaLabel","ModalToggle","innerRef","ref","SearchResultModal","modal","modalNode","modalHeader","modalHeaderNode","modalFooter","modalFooterNode","modalBody","ModalBody","Modal","autoFocus","applicationNode","returnFocusRef","returnRef","isOpen","toggle","onModalToggle","zIndex","ModalHeader","modalTitle","ModalFooter","Button","modalCloseButtonText","getInventoryLabel","productInventoryStatus","shippingInventory","shipping","ProductAvailableQuantity","StockLevelLabel","inventoryAttribute","callAddWishlistLine","wishlistId","toastErrorHeader","getCustomerAccount","createdCommerceList","addLinesAsync","buildWishlistLine","update","createGetByCustomerInput","err","_error$data","_error$data2","footer","data","CorrelationId","toasts","customerInput","getWishlistButton","wishlists","defaultWishlistName","_wishlists$0$Commerce","isWishlisted","CommerceListLines","removeFromWishlistButtonText","addToWishlistButtonText","wishlistLineId","foundWishlistItem","commerceListLine","LineId","getWishlistLineIdFromProductId","removeLinesAsync","Id","commerceList","newWishlists","catch","_error$data5","_error$data6","removeItemFromWishlist","productInputs","productInput","ProductInput","simpleProduct","getSimpleProducts","getWishlistByCustomerId","toast","addedProductToWishlistText","type","autoClose","position","canClose","showProgress","wishlistName","listData","CustomerId","CommerceListTypeValue","createCommerceListAsync","_error$data3","_error$data4","moveItemToWishlist","ProductSearchResultItems","cart","simpleProducts","customerInformation","orderTemplates","unitConversions","moduleType","moduleId","allowBackNavigation","quickviewSlot","productComparisonButton","isPriceMinMaxEnabled","productsDimensionAvailabilities","validatedProductAccess","disableBuyButtons","showPrices","productInventoryInformation","orderTemplatesState","setOrderTemplatesState","cartQueue","PQueue","concurrency","updateOrderTemplatesAsync","newOrderTemplates","newOrderTemplate","every","productList","splice","OrderTemplate","GetOrderTemplatesInput","getOrderTemplates","retrieveOrderTemplates","priceResources","priceRangeSeparator","_validatedProductAcce","ProductComponent","freePriceText","priceFree","originalPriceText","currentPriceText","ratingAriaLabel","allowBack","typeName","ProductRecordId","buyAlwaysAdd","onUpdateOrderTemplates","quickViewButton","wishlistButton","inventoryLabel","inventoryStatus","disableBuyButton","showPrice","userHasAccess","HasAccess","swatchItemAriaLabel","addToCartText","updateCartText","removeFromCartText","outOfStockText","priceErrorText","toastStrings","errorHeader","productsAddedToCart","productsRemovedFromCart","productsUpdatedInCart","goToCart","toastGoToCart","noAccessToProduct","toastNoAccessToProduct","inCartTooltipText","transitTooltip","dimensionAvailabilities","dimensionAvailability","masterProductId","MasterProductId","addToOrderTemplateResources","addToOrderTemplateHeader","noOrderTemplatesMessage","noOrderTemplatesDescription","createAnOrderTemplateButtonText","createNewOrderTemplateButtonText","cancelOrderTemplateCreationButtonText","selectTemplatesText","addToTemplateButtonText","lineItemsText","createOrderTemplateHeader","orderTemplateTitle","orderTemplateNameAriaLabel","createOrderTemplateDescription","defaultOrderTemplateName","createOrderTemplateButtonText","cancelNewOrderTemplateCreationButtonText","viewOrderTemplateButtonText","continueShoppingButtonText","itemAddedToOrderTemplateHeaderItemOneText","itemAddedToOrderTemplateHeaderItemFormatText","itemAddedToOrderTemplateHeaderMessageText","duplicatedProductsHeader","duplicatedProductsDescription","updateQuantityButtonText","cancelDuplicateItemsButtonText","addToOrderTemplateButtonText","addToOrderTemplateButtonTooltip","onBuyValidate","onBuyHasAccessValidator","Separator","separator","Title","RangeRefineItemInput","_formattedPriceReverseLookup","Map","_changeMinInputRange","bind","_changeMaxInputRange","_applyCustom","minInput","maxInput","initialMin","initialMax","selectedRefinementCriterion","parentProductRefinerHierarchy","isCustomRangeTypeIntegerSelected","state","validationErrorMin","validationErrorMax","selectedMin","selectedMax","invalidData","isChecked","shouldComponentUpdate","nextProps","nextState","componentDidUpdate","previousProps","updateInputRangerProps","rangeType","_renderInputFields","_this$props$selectedR","_this$props$selectedR2","_this$props$selectedR3","_this$props$selectedR4","_isUndefined","setState","isDisabled","refineItemCommonProps","formAttrs","rangeNameFormat","minInputClassName","maxInputClassName","placeholder","onChange","disabled","event","selectedMinValue","_getInputWithoutFormatting","minTouched","onToggle","maxNum","_validateRange","isSelecting","trim","min","validationErrorRange","inputAsNum","RangeRefineItem","_selectedRefinementCr","_ref2","getLabels","sliderId","minPrice","maxPrice","labelId","labelString","labelPositioning","getSliderThumbs","sliderKey","selectedMinPrice","selectedMaxPrice","_this$props$minValueS","_this$props$maxValueS","minValueSliderThumbAriaLabel","currencyCode","ariaValueText","maxValueSliderThumbAriaLabel","_onRangeUpdate","_onRangeUpdateEnd","_handleRangeTooltipText","_changeMin","_changeMax","_finishChangeMin","_finishChangeMax","String","minValue","maxValue","labels","sliderKeyString","sliderThumbs","touchedMin","touchedMax","updateSliderProps","_renderSlider","_ref3","_this$props$selectedR5","_this$props$selectedR6","_ref4","_this$props$selectedR7","_this$props$selectedR8","formattedSelectedMin","_getFormattedSelectedValue","formattedSelectedMax","minLabel","onFocus","onBlur","maxLabel","placeholderTextMax","ariaAttributes","Slider","inForm","step","orientation","showLabels","showTooltip","onChangeEnd","debounce","handleTooltipText","_changeValue","inputType","selectedKey","touchedKey","validationErrorNaN","_focus","rangeStart","rangeEnd","selectedMaxValue","maxTouched","minNum","setTimeout","current","focus","touched","validationError","sliderChangeNotification","eventType","firstThumbValue","secondThumbValue","_focusOnSliderThumb","document","getElementById","tooltip","RefineItem","anchorType","_this$props$parentPro","_this$props$parentPro2","_this$props","productCountAriaLabel","singleProductCountAriaLabel","children","refineItemAriaLabel","refineItemsAriaLabel","yesText","noText","attrs","_objectWithoutProperties","_excluded","isSingleSelect","RefinerTypeValue","RefinerType","SingleSelect","itemTypeClassName","SourceValue","Rating","_renderRating","labelText","productText","productCount","refineMenuItemAriaLabel","format","dimensionType","toLocaleLowerCase","shouldDisplayAsSwatch","_getShouldDisplayAsSwatch","hasColor","StringExtensions","isNullOrWhitespace","SwatchColorHexCode","hasImage","SwatchImageUrl","hasContentSwatch","_getRefinerUrl","tabIndex","_renderSwatch","checkIfShouldDisplayAsSwatch","_productRefinerValue$","swatchItems","colorHexCode","SwatchComponent","list","isSelectionEnabled","isRefineItem","ratingUserCountAriaLabel","ratingSingleUserCountAriaLabel","_productRefinerValue$2","refinerRating","parseInt","ratingRefiner","selectedRefinerValues","selectedRating","defaultChkProductCount","ratingComponentClass","productCountAriaLabelValue","isMobileView","RatingComponent","avgRating","ratingCount","hideCount","readOnly","moduleTypeName","RefineSubmenu","MaxItems","_onToggleItem","_onToggleSubmenu","isExpanded","isExpandedOnInitialLoad","expanded","isShowFullList","productRefinerHierarchy","hideRating","Collapse","timeout","onEntered","dispatchEvent","Event","_renderChildItems","_renderRange","_renderSingleMultiSelect","isMobile","refinerValuesList","a","b","localeCompare","listItems","child","findMatchingRefinementCriterion","selectedValue","_getRangeType","DisplayTemplateValue","DisplayTemplate","Range","SliderWithBars","itemToggleNotification","onUpdateRefiners","prevState","ProductRefinerValueDataTypeValue","ProductRefinerTypeValue","dataTypeValue","Decimal","refinementCriteria","refinementCriterion","getUpdatedRefinementCriteria","currentRefinementCriteria","updatedRefinementCriteria","toggledItemFound","r","selectedCriterion","next","Text","matchingIndex","findIndex","criterion","validationMessage","isValid","hasAccess","hasAccessToBuy","message","GetCookie","cookies","cookieName","marketCookie","SetCookie","exp","path","maxAge"],"sourceRoot":""}