{"version":3,"sources":["webpack:///./src/modules/dobbies-search-result-container/dobbies-search-result-container.props.autogenerated.ts?cc2b","webpack:///./src/modules/dobbies-search-result-container/dobbies-search-result-container.tsx?652a","webpack:///./src/modules/dobbies-search-result-container/components/separator.tsx?6465","webpack:///./src/modules/dobbies-search-result-container/components/error-message.tsx?e20f","webpack:///./src/modules/dobbies-search-result-container/actions/url-utils.ts?4634","webpack:///./src/modules/dobbies-search-result-container/components/index.ts?4685","webpack:///./src/modules/dobbies-search-result-container/components/modal.tsx?b489","webpack:///./src/modules/dobbies-search-result-container/components/choice-summary.tsx?36ae","webpack:///./src/modules/dobbies-search-result-container/actions/get-refiners-for-collection.ts?25d3","webpack:///./src/modules/dobbies-search-result-container/actions/get-product-refiner-hierarchy.ts?b8ed","webpack:///./src/modules/dobbies-search-result-container/components/product-search-result-items.tsx?d7c2","webpack:///./src/modules/dobbies-search-result-container/components/utilities.ts?36b8","webpack:///./src/modules/dobbies-search-result-container/components/range-refine-item.tsx?80c5","webpack:///./lib/dobbies-search-result-container/module-registration.js?3a5f","webpack:///./src/modules/dobbies-search-result-container/dobbies-search-result-container.view.tsx?0db2","webpack:///./src/modules/dobbies-search-result-container/components/refine-submenu.tsx?8350","webpack:///external \"React\"?c481","webpack:///./src/modules/dobbies-search-result-container/list-page-state.ts?3fd6","webpack:///./src/themes/dobbies/actions/modules-state-share-action.ts?7abf","webpack:///external \"ReactDOM\"?4b2d","webpack:///./src/modules/dobbies-search-result-container/components/feature-search-result-item.tsx?3680","webpack:///./src/modules/dobbies-search-result-container/actions/get-full-products-by-collection.ts?9dc1","webpack:///./src/modules/dobbies-search-result-container/components/title.tsx?7c91","webpack:///./src/modules/dobbies-search-result-container/actions/base-collection-action.ts?fd56","webpack:///./src/themes/dobbies/views/custom-components/dobbies-modal.tsx?663a","webpack:///./src/modules/dobbies-search-result-container/actions/get-mapped-search-configuration.ts?f5f8","webpack:///./src/modules/dobbies-search-result-container/components/link.tsx?a40c","webpack:///./src/modules/dobbies-search-result-container/components/refine-item.tsx?fa69"],"names":["expandRefinersCount","SearchResultContainer","React","constructor","props","state","super","sortByDropdownOptions","key","sortOptions","sortByOptionRelevanceDesc","value","this","resources","sortByOptionNameAsc","sortByOptionNameDesc","sortByOptionPriceAsc","sortByOptionPriceDesc","sortByOptionRatingDesc","_pageType","context","request","urlTokens","pageType","expandrefinerCount","defaultPageNumber","_getActivePrice","async","products","data","listPageState","result","activeProducts","productRecIds","ArrayExtensions","hasElements","map","prod","RecordId","projectDomain","ChannelId","apiSettings","channelId","CatalogId","catalogId","cart","getCartFromCustomer","actionContext","affliations","AffiliationLines","getActivePricesAsync","callerContext","queryResultSettings","Date","then","activePricesResponse","productPrices","discountLines","priceResp","DiscountLines","length","setState","showProdPrice","activePrice","find","price","ProductId","Price","CustomerContextualPrice","BasePrice","Math","max","TradeAgreementPrice","AdjustedPrice","catch","error","trace","message","telemetry","exception","debug","Error","_getSearchResultModal","SearchResultModal","modalCloseButtonText","modalTitle","isOpen","modalIsOpen","returnRef","_modalToggleRef","onModalToggle","_toggleModal","_getCollectionTitle","collectionTitle","query","q","category","SearchResultContainer_1","getFriendlyName","locale","NameTranslations","Name","productCountNumber","productCountText","undefined","totalProductCount","count","format","numberOfProducts","oneProduct","pageName","telemetryPageName","toLowerCase","titlePrefix","Title","className","text","searchTextPrefix","titleText","titleCount","TitleContainer","title","_getCategoryHierarchy","categoryHierarchy","CategoryHierarchyContainer","tag","categoryHierarchyList","index","Link","ariaLabel","categoryLinkAriaLabel","href","Url","categoryHierarchySeparator","Separator","separator","_getSortingDropDown","activeDropdown","_getCurrentlySelectedOption","sortingState","selectedSortByOption","dropdwonOptions","app","config","hideRating","filter","dropdownOption","SortingContainer","sortByDropDown","LabeledDropdown","labelClassname","labelText","sortByDropdownLabel","dropdownId","dropdownClassname","toggleColor","dropdownOptions","selectedOption","onSelectOption","_updateSortByDropdown","ref","_sortAndFilterContainerRef","_getPagination","fullUrl","getCurrentUrl","itemsPerPage","skipCount","currentPageNumber","skip","totalItems","previousText","flipperPrevious","nextText","flipperNext","UncontrolledPagination","role","paginationAriaLabel","url","qsp","items","startingItem","_renderPrev","_renderNext","previousAriaLabel","nextAriaLabel","telemetryContent","_getRefineMenu","tempRangeTypeTODO","inputRange","validRefiners","updateRefinerPanel","refiners","refiner","Values","activeRefiners","activeFilters","_getexpandRefinerCount","sortedRefiners","sort","a","b","KeyName","localeCompare","startingRefinerList","startingRefiners","indexOf","endingRefiners","startingRefiner","expandedRefiners","RefineMenuContainer","RefinerSectionContainer","productRefinerHierarchy","RefineSubmenu","selectedRefinerValues","refineItemCommonProps","_refineItemCommonProps","minValueSliderThumbAriaLabel","maxValueSliderThumbAriaLabel","onUpdateRefiners","_onUpdateRefiners","urlBuilder","_buildRefinerUrl","isDisabled","isExpandedOnInitialLoad","moduleId","id","moduleTypeName","typeName","_getChoiceSummary","selectedRefiners","ChoiceSummary","classNames","clearAllText","label","choiceSummaryLabel","selectedChoices","refinerHierarchy","choiceFormat","choiceRangeValueFormat","onChoiceClicked","_onChoiceClicked","_buildRefinerUrlForChoiceSummary","choiceAriaLabel","_getProducts","imageSettings","allowBackNavigation","breaCrumbType","breadcrumbType","allowBack","quickviewslot","slots","quickview","isPriceMinMaxFeatureState","featureState","ProductSearchResultItems","moduleType","quickviewSlot","channelInventoryConfigurationId","isPriceMinMaxEnabled","IsEnabled","wishlists","isMobile","notification","requestContext","warning","window","history","pushState","buildListPageUrl","_getSortColumnFromSelectedOption","isUpdated","transaction","sortingCritera","Columns","option","searchConfiguration","mappedConfiguration","sortColumn","sortCriteria","activeSortColumn","parseQueryParam","activeMappedConfig","mappedSearchConfig","ColumnName","IsDescending","itemToggleNotification","updatedRefinementCriteria","getUpdatedRefinementCriteria","newRefinementCriteria","currentRefinementCriteria","clearAll","dropdownElementId","current","dropdownElement","document","getElementById","setTimeout","focus","selectedChoice","choiceClicked","selectedCriterion","isMatchingRefinementCriterion","selectedRefiner","isClearAll","refinerCount","all","one","two","three","four","paginationPreviousText","paginationNextText","_viewport","device","Type","bind","_updateViewport","pending","placeholderTextMax","minLabel","maxLabel","rangeNameFormat","validationErrorNaN","validationErrorNotNumber","validationErrorRange","validationErrorNotRange","getTelemetryObject","friendlyName","querySorting","sorting","JSON","parse","decodeURIComponent","pageSize","hydrateRefinersFromUrl","reaction","input","GetFullProductsByCollectionInput","Paging","Top","Skip","Sorting","itemId","stringify","productId","Recommendation","recommendation","includeAttributes","getCollectionProducts","productResults","enableAffiliationBasedPricing","refinerInput","RefinersByCollectionInput","getCollectionRefinersAction","featureProduct","listPageStateFeature","nameTranslations","nameTranslation","item","Language","Text","componentDidMount","MsDyn365","isBrowser","addEventListener","componentWillUnmount","removeEventListener","render","searchProduct","errorText","resultCategoryNotFoundText","resultSearchNotFoundText","productsComponent","featureComponent","FeatureSearchResultItem","product","searchResultContainerViewProps","TitleViewProps","disableHierarchy","refineMenu","classnames","moduleProps","sortByOptions","pagination","ProductsContainer","ProductSectionContainer","CategoryNavContainer","RefineAndProductSectionContainer","choiceSummary","modalToggle","ModalToggle","innerRef","onClick","searchResultModal","errorMessage","ErrorMessage","FeatureSearchContainer","similarLookProduct","renderView","_getViewport","innerWidth","gridSettings","xs","w","sm","md","lg","__decorate","computed","observable","observer","compressedRefinerKeys","compressedRefinerArray","compressedRefiner","parsedRefiner","forEach","refinerKey","Boolean","sortingColumns","searchParams","delete","first","second","RefinerRecordId","set","compressedRefiners","push","compressRefiners","toString","URL","location","requestUrl","modal","modalNode","modalHeader","modalHeaderNode","modalFooter","modalFooterNode","modalBody","ModalBody","Modal","autoFocus","applicationNode","returnFocusRef","toggle","zIndex","ModalHeader","ModalFooter","Button","closeButtonGlyph","_onClick","e","preventDefault","stopPropagation","target","currentTarget","getAttribute","_getSelectedRefinerChoice","itemClicked","nextItemToFocus","nextSibling","payLoad","getPayloadObject","_getKeyForRefinerValue","selectedRefinersMap","contentAction","etext","clearAllAttributes","getTelemetryAttributes","listItemProps","attribute","productRefinerValue","overallFormat","rangeFormat","refinerValueName","refinerName","parent","hierarchy","DataTypeValue","ProductRefinerValueDataTypeValue","Range","RangeInput","replace","_formatPrice","LeftValueBoundString","UnitText","RightValueBoundString","LeftValueBoundLocalizedString","amount","currency","priceAmount","Number","Intl","NumberFormat","style","currencyDisplay","minimumFractionDigits","selected","innerText","trim","DefaultValues","getProductRefinerHierarchy","searchCriteria","ctx","getProductSearchRefinersAsync","productRefiners","productRefiner","BaseCollectionInput","getCacheObjectType","dataCacheType","actionDataAction","createObservableDataAction","action","searchProductId","CategoryIds","defaultCategoryIdValue","Context","Refinement","isUpdateRefinerPanel","searchText","SearchCondition","searchObject","isNaN","RecommendationListId","Ids","defaultProductIdValue","args","createBaseCollectionInput","getInventoryLabel","AttributeValues","inventoryAttribute","TextValue","productWithTempDeliveryModes","isCnC","isHomeDelivery","clubPlusBanner","productsWithDelivery","setProductsWithDelivery","useState","fulfillmentAttributeName","fulfillmentAttributeTextValue","useEffect","showClubPlusBanner","prodId","newArr","val","hideClubPlusBanner","ProductComponent","freePriceText","priceFree","originalPriceText","currentPriceText","ratingAriaLabel","inventoryLabel","discountLine","badgeLink","clubPlusBadgeLink","showBanner","hideBanner","quickViewButton","ProductRefinerTypeValue","ProductRefinerSource","isRangeType","dataTypeValue","AttributeDataType","Currency","Decimal","Integer","findMatchingRefinementCriterion","refinementCriteria","refinementCriterion","RefinerSourceValue","toggledItemFound","isSelecting","next","rangeStart","rangeEnd","TrueFalse","parentProductRefinerHierarchy","RefinerTypeValue","RefinerType","SingleSelect","child","matchingIndex","findIndex","criterion","splice","RangeRefineItem","_formattedPriceReverseLookup","Map","getLabels","sliderId","minPrice","maxPrice","labelId","labelString","labelPositioning","getSliderThumbs","sliderKey","selectedMin","selectedMinPrice","selectedMax","selectedMaxPrice","currencyCode","ariaValueText","_onRangeUpdate","_onRangeUpdateEnd","_handleRangeTooltipText","_changeMin","_changeMax","_finishChangeMin","_finishChangeMax","minInput","maxInput","selectedRefinementCriterion","initialMin","initialMax","String","minValue","maxValue","labels","sliderKeyString","sliderThumbs","isChecked","validationErrorMin","validationErrorMax","touchedMin","touchedMax","shouldComponentUpdate","nextProps","nextState","componentDidUpdate","previousProps","updateSliderProps","rangeType","_renderInputFields","_renderSlider","formAttrs","minInputClassName","maxInputClassName","formattedSelectedMin","_getFormattedSelectedValue","formattedSelectedMax","onChange","onFocus","onBlur","placeholder","ariaAttributes","Slider","Object","inForm","min","step","orientation","showLabels","showTooltip","onChangeEnd","debounce","handleTooltipText","event","_changeValue","inputType","selectedKey","touchedKey","_getInputWithoutFormatting","selectedMinValue","minTouched","onToggle","maxNum","_focus","_validateRange","selectedMaxValue","maxTouched","minNum","touched","validationError","cultureFormatter","formatCurrency","inputAsNum","get","sliderChangeNotification","eventType","firstThumbValue","secondThumbValue","_focusOnSliderThumb","element","tooltip","binding","modules","dataActions","registerSanitizedActionPath","sanitizedActionPath","dataAction","default","prototype","RegistrationId","c","require","$type","da","name","path","runOn","iNM","ns","n","p","pdp","__bindings__","viewDictionary","cn","createSearchResultModal","oosProps","modalProps","cloneElement","createModalBody","renderSort","renderRefiner","slotBrowse","Node","submenu","Fragment","renderCategoryHierarchy","renderTitleAndProductCount","SearchResultContainerView","currentCategory","browse","browseButtonText","showModal","setShowModal","categoryTitle","SetCategoryTitle","isSearchPage","toLocaleLowerCase","currentCategoryName","update","ModulesStateShareInput","categoryName","_modalToggle","Module","DobbiesModal","modalBodySlots","_onToggleItem","_onToggleSubmenu","expanded","SourceValue","Rating","pathname","includes","_renderChildItems","_renderRange","_renderSingleMultiSelect","refinerValuesList","listItems","RefineItem","selectedValue","_getRangeType","DisplayTemplateValue","DisplayTemplate","SliderWithBars","prevState","module","exports","ListPageState","ListPageStateInput","getCacheKey","listPageStateAction","createListPageInput","inputData","sampleStateAction","customerLoyaltyTierId","ReactDOM","productName","productRecordId","productUrl","getProductPageUrlSync","fallbackImage","getFallbackImageUrl","ItemId","onTelemetryClick","imageUrl","altText","img","src","imageProps","fallBackSrc","Image","loadFailureBehavior","renderProductPlacementImage","PrimaryImageUrl","featureSimilarLooksTitle","ProductListInventoryFilteringOptions","isOutOfStock","channelInventoryConfiguration","InventoryProductAttributeRecordId","InventoryOutOfStockAttributeValueText","returnProductsBasedOnInventoryInformation","ObjectExtensions","isNullOrUndefined","productListInventoryDisplay","HideOOS","filteredProducts","filterOutOfStockProducts","SortOOS","inStockProducts","outOfStockProducts","concat","sortsProductsBasedOnAvailability","returnProducts","productSearchResults","metadataCount","productSearchResultsWithImages","productSearchResult","newImageUrl","generateProductImageUrl","inventoryLevel","InventoryLevels","threshold","enableStockCheck","getInventoryConfigurationAsync","inventoryRanges","promise","searchCriteriaInput","IncludeAttributes","SkipVariantExpansion","categoryId","searchByCriteriaAsync","metadata","toJS","buildCacheKey","convertToString","inputClassConstuctor","QueryResultSettingsProxy","fromInputData","QueryResultSettings","queryRefiners","getUpdateRefinerPanel","modalBodyElement","sortByOptionRatingAsc","sortByOptionBestSelling","sortByOptionNewScore","sortByOptionTrendingScore","MappedSearchInput","getMappedSearchConfiguration","getSearchConfigurationAsync","ProductSortColumns","toUpperCase","createInput","getMappedSearchConfigurationDataAction","anchorType","children","attrs","isSingleSelect","Single","itemTypeClassName","_getRefinerUrl","tabIndex","Count","refinerRating","parseInt","ratingRefiner","selectedRating","ratingComponentClass","RatingComponent","avgRating","ratingCount","hideCount","readOnly"],"mappings":"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","file":"static/js/118.dada89ba1f870ac35103.chunk.js","sourcesContent":["/**\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. See License.txt in the project root for license information.\r\n * IDobbiesSearchResultContainer containerModule Interface Properties\r\n * THIS FILE IS AUTO-GENERATED - MANUAL MODIFICATIONS WILL BE LOST\r\n */\r\n\r\nimport * as Msdyn365 from '@msdyn365-commerce/core';\r\nimport * as React from 'react';\r\n\r\nexport const enum expandRefinersCount {\r\n all = 'all',\r\n one = 'one',\r\n two = 'two',\r\n three = 'three',\r\n four = 'four'\r\n}\r\n\r\nexport interface IDobbiesSearchResultContainerConfig extends Msdyn365.IModuleConfig {\r\n itemsPerPage?: number;\r\n allowBackNavigation?: boolean;\r\n imageSettings?: Msdyn365.IImageSettings;\r\n className?: string;\r\n expandRefinersCount?: expandRefinersCount;\r\n disableHierarchy?: boolean;\r\n startingRefinerList?: string[];\r\n includeAttributes?: boolean;\r\n enableAffiliationBasedPricing?: boolean;\r\n enableOutOfStockButton?: boolean;\r\n updateRefinerPanel?: boolean;\r\n clubPlusBadgeLink?: string;\r\n}\r\n\r\nexport interface IDobbiesSearchResultContainerResources {\r\n noResultsForRefinersText: string;\r\n resultCategoryNotFoundText: string;\r\n resultSearchNotFoundText: string;\r\n paginationAriaLabel: string;\r\n priceFree: string;\r\n originalPriceText: string;\r\n currentPriceText: string;\r\n ratingAriaLabel: string;\r\n flipperNext: string;\r\n flipperPrevious: string;\r\n searchTextPrefix: string;\r\n numberOfProducts: string;\r\n oneProduct: string;\r\n categoryLinkAriaLabel: string;\r\n sortByDropdownLabel: string;\r\n sortByOptionNameAsc: string;\r\n sortByOptionNameDesc: string;\r\n sortByOptionPriceAsc: string;\r\n sortByOptionPriceDesc: string;\r\n sortByOptionRatingDesc: string;\r\n sortByOptionRelevanceDesc: string;\r\n placeholderTextMax: string;\r\n minLabel: string;\r\n rangeNameFormat: string;\r\n maxLabel: string;\r\n validationErrorNotNumber: string;\r\n validationErrorNotRange: string;\r\n clearAllText: string;\r\n choiceSummaryLabel: string;\r\n choiceFormat: string;\r\n choiceRangeValueFormat: string;\r\n choiceAriaLabel: string;\r\n modalTitle: string;\r\n modalCloseButtonText: string;\r\n minValueSliderThumbAriaLabel: string;\r\n maxValueSliderThumbAriaLabel: string;\r\n featureSimilarLooksTitle: string;\r\n browseButtonText: string;\r\n outOfStockNavText: string;\r\n showOutofStockBtn: string;\r\n hideOutOfStockBtn: string;\r\n}\r\n\r\nexport interface IDobbiesSearchResultContainerProps extends Msdyn365.IModule {\r\n resources: IDobbiesSearchResultContainerResources;\r\n config: IDobbiesSearchResultContainerConfig;\r\n slots: {\r\n browse: React.ReactNode[];\r\n quickview: React.ReactNode[];\r\n };\r\n}\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\n/* eslint-disable no-duplicate-imports */\r\n\r\nimport {\r\n CategoryHierarchy as CategoryHierarchyData,\r\n IProductRefinerHierarchy,\r\n IProductsDimensionsAvailabilities\r\n} from '@msdyn365-commerce/commerce-entities';\r\nimport MsDyn365 from '@msdyn365-commerce/core';\r\nimport { getCartFromCustomer } from '@msdyn365-commerce/global-state';\r\nimport {\r\n format,\r\n ProductPrice,\r\n ProductRefinerValue,\r\n ProjectionDomain,\r\n SortColumn,\r\n TextValueTranslation,\r\n DiscountLine\r\n} from '@msdyn365-commerce/retail-proxy';\r\nimport { getActivePricesAsync } from '@msdyn365-commerce/retail-proxy/dist/DataActions/ProductsDataActions.g';\r\nimport { ArrayExtensions } from '@msdyn365-commerce-modules/retail-actions';\r\nimport {\r\n getTelemetryObject,\r\n ILabeledDropdownOnChangeNotification,\r\n ILabeledDropdownOption,\r\n IModuleProps,\r\n INodeProps,\r\n ITelemetryContent,\r\n LabeledDropdown,\r\n UncontrolledPagination\r\n} from '@msdyn365-commerce-modules/utilities';\r\nimport classnames from 'classnames';\r\nimport { computed, observable, reaction, transaction } from 'mobx';\r\nimport { observer } from 'mobx-react';\r\nimport * as React from 'react';\r\n\r\nimport {\r\n buildListPageUrl,\r\n getCollectionProducts,\r\n getCollectionRefinersAction,\r\n getCurrentUrl,\r\n GetFullProductsByCollectionInput,\r\n parseQueryParam,\r\n RefinersByCollectionInput,\r\n sortOptions\r\n} from './actions';\r\nimport { hydrateRefinersFromUrl } from './actions/url-utils';\r\nimport {\r\n ErrorMessage,\r\n FeatureSearchResultItem,\r\n getUpdatedRefinementCriteria,\r\n IChoiceSummaryClickNotification,\r\n IRefineItemCommonProps,\r\n IRefineItemToggleNotification,\r\n ISearchResultModalViewProps,\r\n isMatchingRefinementCriterion,\r\n Link,\r\n ModalToggle,\r\n ProductSearchResultItems,\r\n SearchResultModal,\r\n Separator,\r\n Title\r\n} from './components';\r\nimport ChoiceSummary from './components/choice-summary';\r\nimport RefineSubmenu from './components/refine-submenu';\r\nimport { IDobbiesSearchResultContainerData } from './dobbies-search-result-container.data';\r\nimport { expandRefinersCount, IDobbiesSearchResultContainerProps } from './dobbies-search-result-container.props.autogenerated';\r\n\r\nexport interface ISearchResultContainerViewProps extends IDobbiesSearchResultContainerProps {\r\n products?: React.ReactNode;\r\n className?: string;\r\n SearchResultContainer: IModuleProps;\r\n TitleViewProps: ITitleViewProps;\r\n categoryHierarchy: ICategoryHierarchyViewProps;\r\n pagination?: React.ReactNode;\r\n ProductsContainer: INodeProps;\r\n ProductSectionContainer: INodeProps;\r\n refineMenu: IRefineMenuViewProps;\r\n sortByOptions: ISortByViewProps;\r\n choiceSummary?: React.ReactNode;\r\n modalToggle: React.ReactNode;\r\n searchResultModal: ISearchResultModalViewProps;\r\n isMobile: boolean;\r\n CategoryNavContainer: INodeProps;\r\n RefineAndProductSectionContainer: INodeProps;\r\n errorMessage: React.ReactNode;\r\n FeatureSearchContainer: INodeProps;\r\n similarLookProduct?: React.ReactNode;\r\n productPrices?: ProductPrice[];\r\n}\r\n\r\nexport interface ITitleViewProps {\r\n TitleContainer: INodeProps;\r\n title: ISearchResultTitle;\r\n}\r\n\r\nexport interface IRefineMenuViewProps {\r\n RefineMenuContainer: INodeProps;\r\n RefinerSectionContainer: INodeProps;\r\n refiners?: React.ReactNode[];\r\n endingRefiners?: React.ReactNode[];\r\n}\r\n\r\nexport interface ICategoryHierarchyViewProps {\r\n categoryHierarchyList?: React.ReactNode[];\r\n categoryHierarchySeparator?: React.ReactNode;\r\n CategoryHierarchyContainer: INodeProps;\r\n}\r\n\r\nexport interface ISortByViewProps {\r\n SortingContainer: INodeProps;\r\n sortByDropDown?: React.ReactNode;\r\n}\r\n\r\nexport type GridSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\r\n\r\n/**\r\n * Title component for search result container.\r\n */\r\nexport interface ISearchResultTitle {\r\n titlePrefix?: React.ReactNode;\r\n titleText?: React.ReactNode;\r\n titleCount?: React.ReactNode;\r\n}\r\n\r\nexport interface ISearchResultContainerState {\r\n sortingState: ISortByCollectionState;\r\n modalIsOpen: boolean;\r\n refiners: IProductRefinerHierarchy[];\r\n discountLines: (DiscountLine[] | undefined)[];\r\n showProdPrice: boolean;\r\n productsDimensionAvailabilities?: IProductsDimensionsAvailabilities[][];\r\n isUpdated: boolean;\r\n}\r\n\r\ninterface ISortByCollectionState {\r\n selectedSortByOption: ILabeledDropdownOption;\r\n pending: boolean;\r\n}\r\n\r\n/**\r\n *\r\n * SearchResultContainer component.\r\n * @extends {React.PureComponent>}\r\n */\r\n@observer\r\nexport default class SearchResultContainer extends React.PureComponent<\r\n IDobbiesSearchResultContainerProps,\r\n ISearchResultContainerState\r\n> {\r\n @computed get isMobile(): boolean {\r\n return this._viewport === 'xs' || this._viewport === 'sm';\r\n }\r\n\r\n private readonly sortByDropdownOptions: ILabeledDropdownOption[] = [\r\n { key: sortOptions.sortByOptionRelevanceDesc, value: this.props.resources.sortByOptionRelevanceDesc },\r\n { key: sortOptions.sortByOptionNameAsc, value: this.props.resources.sortByOptionNameAsc },\r\n { key: sortOptions.sortByOptionNameDesc, value: this.props.resources.sortByOptionNameDesc },\r\n { key: sortOptions.sortByOptionPriceAsc, value: this.props.resources.sortByOptionPriceAsc },\r\n { key: sortOptions.sortByOptionPriceDesc, value: this.props.resources.sortByOptionPriceDesc },\r\n { key: sortOptions.sortByOptionRatingDesc, value: this.props.resources.sortByOptionRatingDesc }\r\n ];\r\n\r\n private readonly _refineItemCommonProps: IRefineItemCommonProps;\r\n\r\n private readonly _pageType: string | undefined = this.props.context.request.urlTokens.pageType;\r\n\r\n @observable\r\n private _viewport: GridSize;\r\n\r\n private readonly _modalToggleRef: React.RefObject;\r\n\r\n private readonly _sortAndFilterContainerRef: React.RefObject;\r\n\r\n private expandrefinerCount: number | undefined = 0;\r\n\r\n private readonly telemetryContent: ITelemetryContent;\r\n\r\n private productPrices: ProductPrice[];\r\n\r\n private readonly defaultPageNumber = 0;\r\n\r\n public static getFriendlyName(locale: string, nameTranslations?: TextValueTranslation[]): string | undefined {\r\n let nameTranslation: TextValueTranslation | undefined;\r\n if (locale && nameTranslations && nameTranslations.length > 0) {\r\n nameTranslation = nameTranslations.find(item => item.Language!.toLowerCase() === locale.toLowerCase());\r\n }\r\n\r\n return nameTranslation && nameTranslation.Text;\r\n }\r\n\r\n constructor(props: IDobbiesSearchResultContainerProps, state: ISearchResultContainerState) {\r\n super(props);\r\n this._viewport =\r\n props.context.request && props.context.request.device && props.context.request.device.Type === 'Mobile' ? 'xs' : 'lg';\r\n this._modalToggleRef = React.createRef();\r\n this._sortAndFilterContainerRef = React.createRef();\r\n this._toggleModal = this._toggleModal.bind(this);\r\n this._updateViewport = this._updateViewport.bind(this);\r\n this.productPrices = [];\r\n this.state = {\r\n sortingState: {\r\n pending: false,\r\n selectedSortByOption: this.sortByDropdownOptions[0]\r\n },\r\n modalIsOpen: false,\r\n refiners: [],\r\n discountLines: [],\r\n showProdPrice: false,\r\n isUpdated: false\r\n };\r\n const { placeholderTextMax, minLabel, maxLabel, rangeNameFormat } = this.props.resources;\r\n\r\n const locale = this.props.context.request.locale;\r\n const telemetry = this.props.telemetry;\r\n const validationErrorNaN = this.props.resources.validationErrorNotNumber;\r\n const validationErrorRange = this.props.resources.validationErrorNotRange;\r\n this._refineItemCommonProps = {\r\n telemetry,\r\n locale,\r\n placeholderTextMax,\r\n minLabel,\r\n maxLabel,\r\n rangeNameFormat,\r\n validationErrorNaN,\r\n validationErrorRange\r\n };\r\n this.telemetryContent = getTelemetryObject(\r\n this.props.context.request.telemetryPageName!,\r\n this.props.friendlyName,\r\n this.props.telemetry\r\n );\r\n\r\n // Initalization of list page\r\n this.props.data.products.then(products => {\r\n this.props.data.listPageState.then(listPageState => {\r\n if (this._pageType === 'Category') {\r\n listPageState.pageType = 'Category';\r\n } else {\r\n listPageState.pageType = 'Search';\r\n }\r\n\r\n let querySorting: SortColumn[] = [];\r\n\r\n if (this.props.context.request.query && this.props.context.request.query.sorting) {\r\n querySorting = JSON.parse(decodeURIComponent(this.props.context.request.query.sorting)) as SortColumn[];\r\n }\r\n\r\n listPageState.currentPageNumber =\r\n (this.props.context.request.query && +this.props.context.request.query.skip / (this.props.config.itemsPerPage || 10)) ||\r\n 0;\r\n listPageState.sortingCritera = { Columns: querySorting };\r\n listPageState.pageSize = this.props.config.itemsPerPage || 10;\r\n listPageState.activeProducts = products.products;\r\n listPageState.totalProductCount = products.count;\r\n listPageState.activeFilters = hydrateRefinersFromUrl(this.props.context.request);\r\n\r\n // Initialize reaction based on listPageState properties\r\n reaction(\r\n () => {\r\n return [\r\n listPageState.activeFilters && listPageState.activeFilters.length,\r\n listPageState.currentPageNumber,\r\n listPageState.sortingCritera && this.state.isUpdated\r\n ];\r\n },\r\n () => {\r\n const input = new GetFullProductsByCollectionInput(\r\n listPageState.pageType,\r\n this.props.context.request.apiSettings,\r\n {\r\n Paging: {\r\n Top: this.props.config.itemsPerPage,\r\n Skip: Math.max(listPageState.pageSize * (listPageState.currentPageNumber || 0), 0)\r\n },\r\n count: true,\r\n Sorting: listPageState.sortingCritera || {}\r\n },\r\n listPageState.activeFilters || [],\r\n +(this.props.context.request.urlTokens.itemId || 0),\r\n\r\n this.props.context.request.query && this.props.context.request.query.q\r\n ? this.props.context.request.query.q\r\n : JSON.stringify({\r\n ProductId: this.props.context.request.query?.productId,\r\n Recommendation: this.props.context.request.query?.recommendation\r\n }),\r\n !!(\r\n this.props &&\r\n this.props.config &&\r\n this.props.config.includeAttributes !== undefined &&\r\n this.props.config.includeAttributes\r\n ),\r\n this.props.config.updateRefinerPanel,\r\n this.props.context.request.locale\r\n );\r\n getCollectionProducts(input, this.props.context.actionContext).then(productResults => {\r\n listPageState.activeProducts = productResults.products;\r\n listPageState.totalProductCount = productResults.count;\r\n // if (\r\n // this.props.config.enableAffiliationBasedPricing &&\r\n // this.props.context.actionContext.requestContext?.user?.isAuthenticated\r\n // ) {\r\n // this._getActivePrice();\r\n // }\r\n if (this.props.config.enableAffiliationBasedPricing) {\r\n this._getActivePrice();\r\n }\r\n });\r\n\r\n if (this.props.config.updateRefinerPanel) {\r\n const refinerInput = new RefinersByCollectionInput(\r\n listPageState.pageType,\r\n this.props.context.request.apiSettings,\r\n {\r\n Paging: {\r\n Top: this.props.config.itemsPerPage,\r\n Skip: Math.max(\r\n listPageState.pageSize * (listPageState.currentPageNumber ?? this.defaultPageNumber),\r\n this.defaultPageNumber\r\n )\r\n },\r\n count: true,\r\n Sorting: listPageState.sortingCritera ?? {}\r\n },\r\n listPageState.activeFilters ?? [],\r\n +(this.props.context.request.urlTokens.itemId ?? 0),\r\n this.props.context.request.query?.q\r\n ? this.props.context.request.query.q\r\n : this.props.context.request.query?.productId,\r\n false,\r\n this.props.config.updateRefinerPanel\r\n );\r\n\r\n getCollectionRefinersAction(refinerInput, this.props.context.actionContext)\r\n .then(refiners => {\r\n this.setState({ refiners });\r\n })\r\n .catch(error => {\r\n this.props.telemetry.error(error);\r\n });\r\n }\r\n }\r\n );\r\n });\r\n });\r\n\r\n if (this.props.context.request.query?.productId) {\r\n this.props.data.featureProduct.then(products => {\r\n this.props.data.listPageState.then(listPageStateFeature => {\r\n listPageStateFeature.featureProduct = products;\r\n });\r\n });\r\n }\r\n this._updateViewport();\r\n }\r\n\r\n public componentDidMount(): void {\r\n if (MsDyn365.isBrowser && window.addEventListener) {\r\n window.addEventListener('resize', this._updateViewport);\r\n this._updateViewport();\r\n }\r\n if (this.props.config.enableAffiliationBasedPricing) {\r\n this._getActivePrice();\r\n }\r\n // if (this.props.config.enableAffiliationBasedPricing && this.props.context.actionContext.requestContext?.user?.isAuthenticated) {\r\n // this._getActivePrice();\r\n // }\r\n }\r\n\r\n public componentWillUnmount(): void {\r\n if (MsDyn365.isBrowser && window.removeEventListener) {\r\n window.removeEventListener('resize', this._updateViewport);\r\n }\r\n }\r\n\r\n public render(): JSX.Element {\r\n const { imageSettings, className } = this.props.config;\r\n const { resources } = this.props;\r\n const products = (this.props.data.listPageState.result && this.props.data.listPageState.result.activeProducts) || [];\r\n const searchProduct = (this.props.data.listPageState.result && this.props.data.listPageState.result.featureProduct) || null;\r\n let errorText = '';\r\n if (!products || products.length === 0) {\r\n errorText = this._pageType === 'Category' ? resources.resultCategoryNotFoundText : resources.resultSearchNotFoundText;\r\n }\r\n const productsComponent = this._getProducts();\r\n const featureComponent = (\r\n \r\n );\r\n\r\n const searchResultContainerViewProps = {\r\n ...this.props,\r\n products: productsComponent,\r\n TitleViewProps: this._getCollectionTitle(),\r\n categoryHierarchy: !this.props.config.disableHierarchy && this._getCategoryHierarchy(),\r\n refineMenu: this._getRefineMenu(),\r\n className: classnames('ms-search-result-container', className),\r\n SearchResultContainer: {\r\n moduleProps: this.props,\r\n className: classnames('ms-search-result-container', className)\r\n },\r\n sortByOptions:\r\n this.props.data.listPageState.result && this.props.data.listPageState.result.totalProductCount !== 0\r\n ? this._getSortingDropDown()\r\n : null,\r\n pagination: this._getPagination(),\r\n ProductsContainer: { className: 'ms-search-result-container__Products' },\r\n ProductSectionContainer: { className: 'ms-search-result-container__product-section' },\r\n CategoryNavContainer: { className: 'ms-search-result-container__category-nav-section' },\r\n RefineAndProductSectionContainer: { className: 'ms-search-result-container__refine-product-section' },\r\n choiceSummary: this._getChoiceSummary(),\r\n modalToggle:\r\n this.props.data.listPageState.result && this.props.data.listPageState.result.totalProductCount !== 0 ? (\r\n \r\n ) : null,\r\n searchResultModal: this._getSearchResultModal(),\r\n isMobile: this.isMobile,\r\n errorMessage: errorText && ,\r\n FeatureSearchContainer: { className: 'ms-feature-search-result' },\r\n similarLookProduct:\r\n this.props.data.listPageState.result &&\r\n this.props.data.listPageState.result.featureProduct !== null &&\r\n this.props.data.listPageState.result.featureProduct !== undefined\r\n ? featureComponent\r\n : null,\r\n productPrices: this.productPrices\r\n };\r\n return this.props.renderView(searchResultContainerViewProps) as React.ReactElement;\r\n }\r\n\r\n private readonly _getActivePrice = async (): Promise => {\r\n // Commented Out for Production\r\n // const priceAffiliations = [\r\n // {\r\n // AffiliationId: this.props.context.app.config.AffiliationId,\r\n // LoyaltyTierId: this.props.context.app.config.LoyaltyTierId,\r\n // AffiliationTypeValue: this.props.context.app.config.AffiliationTypeValue,\r\n // ReasonCodeLines: [],\r\n // CustomerId: '',\r\n // ExtensionProperties: []\r\n // }\r\n // ];\r\n\r\n let products = (this.props.data.listPageState.result && this.props.data.listPageState.result.activeProducts) || [];\r\n const productRecIds = ArrayExtensions.hasElements(products) ? products.map(prod => prod.RecordId) : [];\r\n const projectDomain: ProjectionDomain = {\r\n ChannelId: this.props.context.request.apiSettings.channelId,\r\n CatalogId: this.props.context.request.apiSettings.catalogId\r\n };\r\n const cart = await getCartFromCustomer(this.props.context.actionContext);\r\n const affliations = cart?.AffiliationLines;\r\n await getActivePricesAsync(\r\n {\r\n callerContext: this.props.context.actionContext,\r\n queryResultSettings: {}\r\n },\r\n projectDomain,\r\n productRecIds,\r\n new Date(),\r\n null,\r\n affliations,\r\n true\r\n )\r\n .then((activePricesResponse: ProductPrice[]) => {\r\n this.productPrices = activePricesResponse;\r\n const discountLines = activePricesResponse.map(priceResp => priceResp.DiscountLines);\r\n if (this.state.discountLines.length <= 0 && discountLines) {\r\n this.setState({\r\n discountLines: discountLines,\r\n showProdPrice: true\r\n });\r\n }\r\n\r\n products = products.map(prod => {\r\n const activePrice = activePricesResponse.find(price => price.ProductId === prod.RecordId);\r\n if (activePrice) {\r\n prod.Price = activePrice.CustomerContextualPrice ?? prod.Price;\r\n prod.BasePrice = Math.max(\r\n activePrice.BasePrice || 0,\r\n activePrice.TradeAgreementPrice || 0,\r\n activePrice.AdjustedPrice || 0\r\n );\r\n }\r\n return prod;\r\n });\r\n this.props.data.listPageState.then(listPageState => {\r\n listPageState.activeProducts = products;\r\n });\r\n })\r\n .catch((error: Error) => {\r\n this.setState({\r\n showProdPrice: true\r\n });\r\n this.props.context.actionContext.trace(error.message);\r\n this.props.context.actionContext.telemetry.exception(error);\r\n this.props.context.actionContext.telemetry.debug(\r\n '[get Affiliation based price on search result container ]Error executing action'\r\n );\r\n throw new Error('[get Affiliation based price on search result container]Error executing action');\r\n });\r\n };\r\n\r\n private readonly _getSearchResultModal = (): ISearchResultModalViewProps => {\r\n const { resources } = this.props;\r\n return SearchResultModal({\r\n resources: {\r\n modalCloseButtonText: resources.modalCloseButtonText,\r\n modalTitle: resources.modalTitle\r\n },\r\n isOpen: this.state.modalIsOpen,\r\n returnRef: this._modalToggleRef,\r\n onModalToggle: this._toggleModal\r\n });\r\n };\r\n\r\n private readonly _getCollectionTitle = (): ITitleViewProps => {\r\n const { data, context, resources } = this.props;\r\n\r\n let collectionTitle: string | undefined = '';\r\n if (context && context.request && context.request.query && context.request.query.q) {\r\n collectionTitle = `\"${context.request.query.q}\"`;\r\n } else {\r\n collectionTitle =\r\n (data.category.result &&\r\n SearchResultContainer.getFriendlyName(context.request.locale, data.category.result.NameTranslations)) ||\r\n (data.category.result && data.category.result.Name);\r\n }\r\n let productCountText = '';\r\n let productCountNumber: number | undefined;\r\n if (data.listPageState && data.listPageState.result && data.listPageState.result.totalProductCount !== undefined) {\r\n productCountNumber = data.listPageState.result.totalProductCount;\r\n } else if (data.products && data.products.result) {\r\n productCountNumber = data.products.result.count;\r\n }\r\n\r\n if (productCountNumber && productCountNumber !== 0) {\r\n productCountText =\r\n productCountNumber !== 1\r\n ? format(this.props.resources.numberOfProducts, productCountNumber)\r\n : this.props.resources.oneProduct;\r\n } else {\r\n productCountText = format(this.props.resources.numberOfProducts, 0);\r\n }\r\n const pageName = context.request.telemetryPageName ? `result-count-${context.request.telemetryPageName.toLowerCase()}` : '';\r\n const titlePrefix = ;\r\n const titleText = collectionTitle && <Title className='ms-search-result__collection-title-text' text={collectionTitle} />;\r\n const titleCount = <Title className='ms-search-result__collection-title-count' text={productCountText} />;\r\n\r\n return {\r\n TitleContainer: { className: `ms-search-result-container__title ${pageName}` },\r\n title: {\r\n titlePrefix,\r\n titleText,\r\n titleCount\r\n }\r\n };\r\n };\r\n\r\n private readonly _getCategoryHierarchy = (): ICategoryHierarchyViewProps => {\r\n const { data } = this.props;\r\n const categoryHierarchy = data.categoryHierarchy.result;\r\n const categoryLinks =\r\n categoryHierarchy &&\r\n categoryHierarchy.map((value: CategoryHierarchyData, index: number) => {\r\n return (\r\n <Link\r\n key={index}\r\n text={value.Name}\r\n ariaLabel={`${this.props.resources.categoryLinkAriaLabel} ${value.Name}`}\r\n href={value.Url}\r\n />\r\n );\r\n });\r\n const categoryLinkSeparator = <Separator separator='/' />;\r\n\r\n return {\r\n CategoryHierarchyContainer: { tag: 'nav', className: 'ms-search-result-container__category-hierarchy' },\r\n categoryHierarchyList: categoryLinks,\r\n categoryHierarchySeparator: categoryLinkSeparator\r\n };\r\n };\r\n\r\n private readonly _getSortingDropDown = (): ISortByViewProps => {\r\n const { resources } = this.props;\r\n const activeDropdown = this._getCurrentlySelectedOption() || this.state.sortingState.selectedSortByOption;\r\n let dropdwonOptions = this.sortByDropdownOptions;\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- App config settings are of \"any\" value.\r\n if (this.props.context.app.config.hideRating) {\r\n dropdwonOptions = this.sortByDropdownOptions.filter(dropdownOption => dropdownOption.key !== 'AverageRating-Desc');\r\n }\r\n const dropdown = (\r\n <LabeledDropdown\r\n labelClassname='reviews-list-sort-by'\r\n labelText={resources.sortByDropdownLabel}\r\n dropdownId='categorySortByDropdown'\r\n dropdownClassname='reviews-list-dropdown'\r\n toggleColor='link'\r\n dropdownOptions={dropdwonOptions}\r\n selectedOption={activeDropdown}\r\n onSelectOption={this._updateSortByDropdown}\r\n ref={this._sortAndFilterContainerRef}\r\n />\r\n );\r\n return {\r\n SortingContainer: { className: 'ms-search-result-container__Sort-by-category' },\r\n sortByDropDown: dropdown\r\n };\r\n };\r\n\r\n private readonly _getPagination = (): React.ReactNode => {\r\n const { config, context, data, resources } = this.props;\r\n const listPageState = data && data.listPageState && data.listPageState.result;\r\n const fullUrl = getCurrentUrl(context.request);\r\n const itemsPerPage = config.itemsPerPage || 10;\r\n const skipCount =\r\n listPageState && listPageState.currentPageNumber !== null\r\n ? listPageState.currentPageNumber * (this.props.config.itemsPerPage || 10)\r\n : (this.props.context.request.query && +this.props.context.request.query.skip) || 0;\r\n const totalItems = (listPageState && listPageState.totalProductCount) || 0;\r\n const previousText = resources.flipperPrevious;\r\n const nextText = resources.flipperNext;\r\n\r\n if (totalItems <= itemsPerPage) {\r\n return null;\r\n }\r\n return (\r\n <UncontrolledPagination\r\n className='ms-search-result-container__pagination'\r\n role='navigation'\r\n aria-label={resources.paginationAriaLabel}\r\n url={fullUrl.href}\r\n qsp='skip'\r\n items={totalItems}\r\n itemsPerPage={itemsPerPage}\r\n startingItem={skipCount}\r\n previousText={this._renderPrev(previousText)}\r\n nextText={this._renderNext(nextText)}\r\n previousAriaLabel={previousText}\r\n nextAriaLabel={nextText}\r\n telemetryContent={this.telemetryContent}\r\n />\r\n );\r\n };\r\n\r\n private readonly _getRefineMenu = (): IRefineMenuViewProps => {\r\n const { data, context, config } = this.props;\r\n const tempRangeTypeTODO = context.request.query && context.request.query.inputRange ? 'input' : 'slider';\r\n const validRefiners =\r\n this.props.config.updateRefinerPanel && ArrayExtensions.hasElements(this.state.refiners)\r\n ? this.state.refiners.filter(refiner => {\r\n return ArrayExtensions.hasElements(refiner.Values);\r\n })\r\n : data.refiners.result &&\r\n data.refiners.result.filter(refiner => {\r\n return ArrayExtensions.hasElements(refiner.Values);\r\n });\r\n\r\n const activeRefiners = (data.listPageState.result && data.listPageState.result.activeFilters) || [];\r\n\r\n this._getexpandRefinerCount(validRefiners && validRefiners.length, config.expandRefinersCount);\r\n\r\n const sortedRefiners =\r\n validRefiners &&\r\n validRefiners.sort((a, b) => {\r\n return a.KeyName!.localeCompare(b.KeyName!);\r\n });\r\n\r\n const startingRefinerList = this.props.config.startingRefinerList || [];\r\n\r\n const startingRefiners = sortedRefiners?.filter(refiner => startingRefinerList.indexOf(refiner.KeyName!) > -1);\r\n\r\n const endingRefiners = sortedRefiners?.filter(refiner => {\r\n const existsInStarting = startingRefiners?.find(startingRefiner => startingRefiner.RecordId === refiner.RecordId);\r\n\r\n return !existsInStarting;\r\n });\r\n\r\n const expandedRefiners = this.expandrefinerCount;\r\n\r\n const subMenus =\r\n startingRefiners &&\r\n startingRefiners.map((productRefinerHierarchy: IProductRefinerHierarchy, index: number) => {\r\n return (\r\n <RefineSubmenu\r\n productRefinerHierarchy={productRefinerHierarchy}\r\n selectedRefinerValues={activeRefiners}\r\n refineItemCommonProps={this._refineItemCommonProps}\r\n minValueSliderThumbAriaLabel={this.props.resources.minValueSliderThumbAriaLabel}\r\n maxValueSliderThumbAriaLabel={this.props.resources.maxValueSliderThumbAriaLabel}\r\n key={index}\r\n onUpdateRefiners={this._onUpdateRefiners}\r\n urlBuilder={this._buildRefinerUrl}\r\n isDisabled={false}\r\n isExpandedOnInitialLoad={!!(expandedRefiners && expandedRefiners > index)}\r\n tempRangeTypeTODO={tempRangeTypeTODO}\r\n context={context}\r\n moduleId={this.props.id}\r\n moduleTypeName={this.props.typeName}\r\n />\r\n );\r\n });\r\n\r\n const endingSubMenus =\r\n endingRefiners &&\r\n endingRefiners.map((productRefinerHierarchy: IProductRefinerHierarchy, index: number) => {\r\n return (\r\n <RefineSubmenu\r\n productRefinerHierarchy={productRefinerHierarchy}\r\n selectedRefinerValues={activeRefiners}\r\n refineItemCommonProps={this._refineItemCommonProps}\r\n minValueSliderThumbAriaLabel={this.props.resources.minValueSliderThumbAriaLabel}\r\n maxValueSliderThumbAriaLabel={this.props.resources.maxValueSliderThumbAriaLabel}\r\n key={index}\r\n onUpdateRefiners={this._onUpdateRefiners}\r\n urlBuilder={this._buildRefinerUrl}\r\n isDisabled={false}\r\n isExpandedOnInitialLoad={!!(expandedRefiners && expandedRefiners > index)}\r\n tempRangeTypeTODO={tempRangeTypeTODO}\r\n context={context}\r\n moduleId={this.props.id}\r\n moduleTypeName={this.props.typeName}\r\n />\r\n );\r\n });\r\n\r\n return {\r\n RefineMenuContainer: { className: 'ms-search-result-container__refine-menu' },\r\n RefinerSectionContainer: { className: 'ms-search-result-container__refiner-section' },\r\n refiners: subMenus,\r\n endingRefiners: endingSubMenus\r\n };\r\n };\r\n\r\n private readonly _getChoiceSummary = (): React.ReactNode => {\r\n const { resources, data, telemetry } = this.props;\r\n const selectedRefiners = (data.listPageState.result && data.listPageState.result.activeFilters) || [];\r\n return (\r\n <ChoiceSummary\r\n classNames='ms-choice-summary-by-category'\r\n clearAllText={resources.clearAllText}\r\n label={resources.choiceSummaryLabel}\r\n selectedChoices={selectedRefiners}\r\n // @ts-expect-error: NOTE Type-unsafe line below, null refinersByCategoryHierarchy case not handled\r\n refinerHierarchy={data.refiners.result}\r\n choiceFormat={resources.choiceFormat}\r\n choiceRangeValueFormat={resources.choiceRangeValueFormat}\r\n telemetry={telemetry}\r\n onChoiceClicked={this._onChoiceClicked}\r\n urlBuilder={this._buildRefinerUrlForChoiceSummary}\r\n choiceAriaLabel={resources.choiceAriaLabel}\r\n telemetryContent={this.telemetryContent}\r\n context={this.props.context}\r\n />\r\n );\r\n };\r\n\r\n private readonly _getProducts = (): JSX.Element => {\r\n const { imageSettings, allowBackNavigation } = this.props.config;\r\n const { resources } = this.props;\r\n const breaCrumbType = this.props.context.app.config.breadcrumbType;\r\n const allowBack = allowBackNavigation && (breaCrumbType === 'back' || breaCrumbType === 'categoryAndBack');\r\n const products = (this.props.data.listPageState.result && this.props.data.listPageState.result.activeProducts) || [];\r\n const quickviewslot = this.props.slots && this.props.slots.quickview && this.props.slots.quickview[0];\r\n const isPriceMinMaxFeatureState = this.props.data.featureState.result?.find(\r\n featureState => featureState.Name === 'Dynamics.AX.Application.RetailSearchPriceRangeFeature'\r\n );\r\n return (\r\n <ProductSearchResultItems\r\n products={products}\r\n context={this.props.context}\r\n imageSettings={imageSettings}\r\n resources={resources}\r\n moduleType={this.props.typeName}\r\n moduleId={this.props.id}\r\n allowBackNavigation={allowBack}\r\n telemetryContent={this.telemetryContent}\r\n quickviewSlot={quickviewslot}\r\n channelInventoryConfigurationId={this.props.data.products.result?.channelInventoryConfigurationId}\r\n isPriceMinMaxEnabled={isPriceMinMaxFeatureState?.IsEnabled}\r\n discountLines={this.state.discountLines}\r\n config={this.props.config}\r\n showProdPrice={this.state.showProdPrice}\r\n wishlists={this.props.data.wishlists.result}\r\n\t\t\t\tisMobile={this.isMobile}\r\n />\r\n );\r\n };\r\n\r\n private readonly _updateSortByDropdown = (notification: ILabeledDropdownOnChangeNotification): void => {\r\n const { context } = this.props;\r\n const requestContext = context && context.request;\r\n const actionContext = context && context.actionContext;\r\n\r\n if (!requestContext || !actionContext || !this.props.data.listPageState.result) {\r\n const error = `[sort-by-category] cannot sort without context: ${!requestContext ? 'requestContext ' : ''} ${\r\n !actionContext ? 'actionContext ' : ''\r\n } could not be found`;\r\n this.props.telemetry.warning(error);\r\n }\r\n\r\n window.history.pushState(\r\n {},\r\n '',\r\n buildListPageUrl(\r\n getCurrentUrl(this.props.context.request),\r\n undefined,\r\n [this._getSortColumnFromSelectedOption(notification.selectedOption)],\r\n undefined\r\n )\r\n );\r\n this.setState({ isUpdated: !this.state.isUpdated, discountLines: [] });\r\n\r\n transaction(() => {\r\n this.props.data.listPageState.result!.currentPageNumber = 0;\r\n this.props.data.listPageState.result!.sortingCritera = {\r\n Columns: [this._getSortColumnFromSelectedOption(notification.selectedOption)]\r\n };\r\n });\r\n };\r\n\r\n private readonly _getSortColumnFromSelectedOption = (option: ILabeledDropdownOption): SortColumn => {\r\n const { data } = this.props;\r\n\r\n if (!data.searchConfiguration.result) {\r\n return {};\r\n }\r\n\r\n const mappedConfiguration = data.searchConfiguration.result.find(searchConfiguration => {\r\n return searchConfiguration.key === option.key;\r\n });\r\n\r\n if (mappedConfiguration) {\r\n return mappedConfiguration.sortColumn;\r\n }\r\n\r\n return {};\r\n };\r\n\r\n private readonly _getCurrentlySelectedOption = (): ILabeledDropdownOption | undefined => {\r\n const { data } = this.props;\r\n const sortCriteria = data.listPageState.result && data.listPageState.result.sortingCritera;\r\n\r\n const activeSortColumn =\r\n (sortCriteria && sortCriteria.Columns && sortCriteria.Columns[0]) ||\r\n (parseQueryParam<SortColumn[]>('sorting', this.props.context.request) || [])[0];\r\n\r\n if (activeSortColumn && data.searchConfiguration.result) {\r\n const activeMappedConfig = data.searchConfiguration.result.find(mappedSearchConfig => {\r\n return (\r\n mappedSearchConfig.sortColumn.ColumnName === activeSortColumn.ColumnName &&\r\n mappedSearchConfig.sortColumn.IsDescending === activeSortColumn.IsDescending\r\n );\r\n });\r\n if (activeMappedConfig) {\r\n return this.sortByDropdownOptions.find(dropdownOption => dropdownOption.key === activeMappedConfig.key);\r\n }\r\n }\r\n\r\n return;\r\n };\r\n\r\n private readonly _onUpdateRefiners = (itemToggleNotification: IRefineItemToggleNotification): void => {\r\n const { context } = this.props;\r\n const requestContext = context && context.request;\r\n const actionContext = context && context.actionContext;\r\n\r\n if (!requestContext || !actionContext || !this.props.data.listPageState.result) {\r\n const error = `Refine menu cannot refine search criteria: ${!requestContext ? 'requestContext ' : ''} ${\r\n !actionContext ? 'actionContext ' : ''\r\n } could not be found`;\r\n this.props.telemetry.warning(error);\r\n }\r\n\r\n const updatedRefinementCriteria = getUpdatedRefinementCriteria(\r\n itemToggleNotification,\r\n (this.props.data.listPageState.result && this.props.data.listPageState.result.activeFilters) || []\r\n );\r\n\r\n window.history.pushState({}, '', buildListPageUrl(getCurrentUrl(this.props.context.request), updatedRefinementCriteria));\r\n transaction(() => {\r\n this.props.data.listPageState.result!.currentPageNumber = 0;\r\n this.props.data.listPageState.result!.activeFilters = updatedRefinementCriteria;\r\n });\r\n };\r\n\r\n private readonly _buildRefinerUrl = (itemToggleNotification: IRefineItemToggleNotification): string => {\r\n if (this.props.data.listPageState.result) {\r\n const newRefinementCriteria = getUpdatedRefinementCriteria(\r\n itemToggleNotification,\r\n this.props.data.listPageState.result.activeFilters || []\r\n );\r\n\r\n return buildListPageUrl(getCurrentUrl(this.props.context.request), newRefinementCriteria);\r\n }\r\n this.props.telemetry.warning('[buildRefinerQueryString]List Page State Not available, unable to build refiner URL');\r\n return '';\r\n };\r\n\r\n private readonly _onChoiceClicked = (notification: IChoiceSummaryClickNotification): void => {\r\n const { data, telemetry } = this.props;\r\n\r\n if (!data.listPageState.result) {\r\n telemetry.warning('[choice-summary-by-category._onChoiceClicked]ListPageState unavailable, unable to update refiners.');\r\n return;\r\n }\r\n\r\n let currentRefinementCriteria = (data.listPageState.result && data.listPageState.result.activeFilters) || [];\r\n\r\n if (!notification.clearAll) {\r\n const selectedChoice = notification.choiceClicked;\r\n if (!selectedChoice) {\r\n telemetry.warning('[choice-summary-by-category._onChoiceClicked] Choice could not be determined');\r\n return;\r\n }\r\n currentRefinementCriteria = currentRefinementCriteria.filter(\r\n (selectedCriterion: ProductRefinerValue) => !isMatchingRefinementCriterion(selectedChoice, selectedCriterion)\r\n );\r\n } else {\r\n currentRefinementCriteria = [];\r\n\r\n // Set focus to sort and filter\r\n const dropdownElementId = this._sortAndFilterContainerRef.current && this._sortAndFilterContainerRef.current.props.dropdownId;\r\n const dropdownElement = dropdownElementId && document.getElementById(dropdownElementId);\r\n setTimeout(() => {\r\n dropdownElement && dropdownElement.focus();\r\n }, 50);\r\n }\r\n\r\n const fullUrl = getCurrentUrl(this.props.context.request);\r\n window.history.pushState({}, '', buildListPageUrl(fullUrl, currentRefinementCriteria));\r\n data.listPageState.result.currentPageNumber = 0;\r\n data.listPageState.result.activeFilters = currentRefinementCriteria;\r\n };\r\n\r\n private readonly _buildRefinerUrlForChoiceSummary = (selectedRefiner: ProductRefinerValue, isClearAll: boolean): string => {\r\n const { data, telemetry } = this.props;\r\n const fullUrl = getCurrentUrl(this.props.context.request);\r\n\r\n if (!data.listPageState.result) {\r\n telemetry.warning('[choice-summary-by-category._buildRefinerUrl]ListPageState unavailable, unable to create refiner URL.');\r\n return fullUrl.href;\r\n }\r\n\r\n let currentRefinementCriteria = (data.listPageState.result && data.listPageState.result.activeFilters) || [];\r\n\r\n if (!isClearAll) {\r\n if (!selectedRefiner) {\r\n telemetry.warning('[choice-summary-by-category._buildRefinerUrl] URL for Choice could not be determined');\r\n return fullUrl.href;\r\n }\r\n currentRefinementCriteria = currentRefinementCriteria.filter(\r\n (selectedCriterion: ProductRefinerValue) => !isMatchingRefinementCriterion(selectedRefiner, selectedCriterion)\r\n );\r\n } else {\r\n currentRefinementCriteria = [];\r\n }\r\n\r\n return buildListPageUrl(fullUrl, currentRefinementCriteria);\r\n };\r\n\r\n private _getViewport(): GridSize {\r\n const { context } = this.props;\r\n\r\n // Always render in mobile viewport on a mobile device\r\n if (context.request && context.request.device && context.request.device.Type === 'Mobile') {\r\n return 'xs';\r\n }\r\n\r\n if (MsDyn365.isBrowser && window.innerWidth) {\r\n const gridSettings = context.request.gridSettings;\r\n if (gridSettings) {\r\n if (gridSettings.xs && window.innerWidth <= gridSettings.xs.w) {\r\n return 'xs';\r\n } else if (gridSettings.sm && window.innerWidth <= gridSettings.sm.w) {\r\n return 'sm';\r\n } else if (gridSettings.md && window.innerWidth <= gridSettings.md.w) {\r\n return 'md';\r\n } else if (gridSettings.lg && window.innerWidth <= gridSettings.lg.w) {\r\n return 'lg';\r\n }\r\n return 'xl';\r\n }\r\n }\r\n\r\n return 'lg';\r\n }\r\n\r\n private _toggleModal(): void {\r\n this.setState({\r\n modalIsOpen: !this.state.modalIsOpen\r\n });\r\n }\r\n\r\n private _updateViewport(): void {\r\n this._viewport = this._getViewport();\r\n\r\n if (this.state.modalIsOpen && !this.isMobile) {\r\n this._toggleModal();\r\n }\r\n }\r\n\r\n private readonly _getexpandRefinerCount = (validRefiners?: number, refinerCount?: expandRefinersCount): void => {\r\n switch (refinerCount) {\r\n case expandRefinersCount.all:\r\n this.expandrefinerCount = validRefiners;\r\n break;\r\n case expandRefinersCount.one:\r\n this.expandrefinerCount = 1;\r\n break;\r\n case expandRefinersCount.two:\r\n this.expandrefinerCount = 2;\r\n break;\r\n case expandRefinersCount.three:\r\n this.expandrefinerCount = 3;\r\n break;\r\n case expandRefinersCount.four:\r\n this.expandrefinerCount = 4;\r\n break;\r\n default:\r\n this.expandrefinerCount = 0;\r\n }\r\n };\r\n\r\n /**\r\n * Renders a Pagination previous text.\r\n * @param paginationPreviousText - Pagination previous text from resources.\r\n * @returns Previous text and flipper icon.\r\n */\r\n private readonly _renderPrev = (paginationPreviousText: string) => {\r\n return (\r\n <div className='msc-pagination__prev'>\r\n <span className='ms-search-result__pagination-left' aria-hidden='true' />\r\n <span className='prev-text'>{paginationPreviousText}</span>\r\n </div>\r\n );\r\n };\r\n\r\n /**\r\n * Renders a Pagination next text.\r\n * @param paginationNextText - Pagination next text from resources.\r\n * @returns Next text and flipper icon.\r\n */\r\n private readonly _renderNext = (paginationNextText: string) => {\r\n return (\r\n <div className='msc-pagination__next'>\r\n <span className='next-text'>{paginationNextText}</span>\r\n <span className='ms-search-result__pagination-right' aria-hidden='true' />\r\n </div>\r\n );\r\n };\r\n}\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt 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<ISeparator> = ({ separator }) => (<span>\r\n {' '}\r\n {separator}\r\n {' '}\r\n</span>);\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt 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<IErrorMessage> = ({ text }) => {\r\n return (\r\n <span className='ms-search-result-container__no-results-message'>\r\n <h5 className='error-text'>\r\n {' '}\r\n {text}\r\n {' '}\r\n </h5>\r\n </span>\r\n );\r\n};\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt 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];\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 <ProductRefinerValue[]>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 = <T>(key: string, requestContext: IRequestContext): T | null => {\r\n if (requestContext.query && requestContext.query[key]) {\r\n return <T>JSON.parse(decodeURIComponent(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(<string>(<unknown>requestContext.url.requestUrl));\r\n};\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\nexport * from './choice-summary';\r\nexport * from './choice-summary.props';\r\nexport * from './error-message';\r\nexport * from './feature-search-result-item';\r\nexport * from './link';\r\nexport * from './modal';\r\nexport * from './product-search-result-items';\r\nexport * from './range-refine-item';\r\nexport * from './refine-item';\r\nexport * from './refine-item.props.common';\r\nexport * from './refine-item-toggle-notification';\r\nexport * from './refine-submenu';\r\nexport * from './separator';\r\nexport * from './title';\r\nexport * from './utilities';\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt 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<HTMLButtonElement> | 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<HTMLButtonElement> | undefined;\r\n onModalToggle(): void;\r\n}\r\n\r\nexport const ModalToggle: React.FC<IModalToggleProps> = (props: IModalToggleProps) => {\r\n const { text, onClick, ariaLabel, innerRef, id } = props;\r\n return (\r\n <button id={id} className='msc-button' aria-label={ariaLabel} onClick={onClick} ref={innerRef}>\r\n {text}\r\n </button>\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: <ModalBody className='msc-review-modal-body' />\r\n };\r\n};\r\n\r\nconst modalNode = (props: ISearchResultModalProps) => {\r\n return (\r\n <Modal\r\n autoFocus={true}\r\n applicationNode='renderPage'\r\n returnFocusRef={props.returnRef}\r\n isOpen={props.isOpen}\r\n toggle={props.onModalToggle}\r\n className='msc-search-result-modal'\r\n zIndex={1050}\r\n />\r\n );\r\n};\r\n\r\nconst modalHeaderNode = (props: ISearchResultModalProps) => {\r\n return <ModalHeader toggle={props.onModalToggle}>{props.resources.modalTitle}</ModalHeader>;\r\n};\r\n\r\nconst modalFooterNode = (props: ISearchResultModalProps) => {\r\n return (\r\n <ModalFooter>\r\n <Button onClick={props.onModalToggle} className='ms-sort-and-filter-modal-close'>\r\n {props.resources.modalCloseButtonText}\r\n </Button>\r\n </ModalFooter>\r\n );\r\n};\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { getPayloadObject, getTelemetryAttributes, IPayLoad } from '@msdyn365-commerce-modules/utilities';\r\nimport { IProductRefinerHierarchy } from '@msdyn365-commerce/commerce-entities';\r\nimport { ProductRefinerValue } from '@msdyn365-commerce/retail-proxy';\r\nimport classnames from 'classnames';\r\nimport { get } from 'lodash';\r\nimport { computed } from 'mobx';\r\nimport { observer } from 'mobx-react';\r\nimport * as React from 'react';\r\nimport { IChoiceSummaryProps } from './choice-summary.props';\r\n// import { isMatchingRefinementCriterion, isRangeType } from './utilities';\r\nimport { isMatchingRefinementCriterion, ProductRefinerValueDataTypeValue } from './utilities';\r\n\r\ninterface IRefinerMap {\r\n key: string;\r\n value: ProductRefinerValue;\r\n}\r\n\r\n/**\r\n * ChoiceSummary component\r\n */\r\n@observer\r\nexport default class ChoiceSummary extends React.Component<IChoiceSummaryProps> {\r\n private closeButtonGlyph: string = 'msi-close-btn';\r\n private payLoad: IPayLoad;\r\n\r\n @computed get selectedRefinersMap(): IRefinerMap[] {\r\n const { selectedChoices } = this.props;\r\n return selectedChoices.map((selectedRefiner: ProductRefinerValue) => {\r\n return {\r\n key: this._getKeyForRefinerValue(selectedRefiner),\r\n value: selectedRefiner\r\n } as IRefinerMap;\r\n });\r\n }\r\n\r\n constructor(props: Readonly<IChoiceSummaryProps>) {\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 } = 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 <div className='msc-choice-summary'>\r\n {items.length > 0 && label && <span className='msc-choice-summary__label'>{label}</span>}\r\n <ul className={classnames(classNames, 'msc-choice-summary__list', 'list-unstyled')}>\r\n {items.map((item: IRefinerMap, index: number) => {\r\n const listItemProps = {\r\n 'aria-posinset': index,\r\n 'aria-setsize': items.length\r\n };\r\n\r\n this.payLoad.contentAction.etext = item.key;\r\n const attribute = getTelemetryAttributes(this.props.telemetryContent!, this.payLoad);\r\n\r\n return (\r\n <li className='msc-choice-summary__list-item' key={item.key} {...listItemProps}>\r\n <a\r\n className='msc-choice-summary__item'\r\n href={this.props.urlBuilder(item.value, false)}\r\n aria-label={`${item.key} ${choiceAriaLabel}`}\r\n onClick={this._onClick}\r\n {...attribute}\r\n >\r\n {item.key}\r\n <span className={`${this.closeButtonGlyph} msc-choice-summary__glyph`} />\r\n </a>\r\n </li>\r\n );\r\n })}\r\n </ul>\r\n {items.length > 0 && clearAllText && <a href={this.props.urlBuilder({}, true)} className={'msc-choice-summary__clear-all'} {...clearAllAttributes} onClick={this._onClick}>{clearAllText}</a>}\r\n </div>\r\n );\r\n }\r\n\r\n private _getKeyForRefinerValue(productRefinerValue: ProductRefinerValue): string {\r\n const { choiceFormat, choiceRangeValueFormat, refinerHierarchy, telemetry } = 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\r\n let refinerValueName: string;\r\n switch (productRefinerValue.DataTypeValue) {\r\n case ProductRefinerValueDataTypeValue.Range:\r\n case ProductRefinerValueDataTypeValue.RangeInput:\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 break;\r\n default:\r\n refinerValueName = productRefinerValue.LeftValueBoundLocalizedString || productRefinerValue.LeftValueBoundString || '';\r\n }\r\n\r\n return overallFormat.replace('{0}', refinerName).replace('{1}', refinerValueName);\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 const priceAmount = (amount && Number(amount)) || 0;\r\n const locale = get(this.props, 'context.request.locale', 'en-US');\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: currency,\r\n minimumFractionDigits: 0\r\n }).format(priceAmount);\r\n } catch (e) {\r\n result = `${priceAmount} ${currency}`;\r\n this.props.telemetry.warning(`Failed to format price for ${result}: ${e}`);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private _onClick = (e: React.MouseEvent<HTMLAnchorElement>): 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')!.indexOf('choice-summary__clear-all') > -1;\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: 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.innerText && itemClicked.innerText.trim()) === selected.key);\r\n return (result && result.value) || undefined;\r\n }\r\n}\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt 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\n\r\nimport { BaseCollectionInput, createBaseCollectionInput } from './base-collection-action';\r\nimport { getProductRefinerHierarchy } from './get-product-refiner-hierarchy';\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 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 ctx\r\n */\r\nasync function action(input: RefinersByCollectionInput, ctx: IActionContext): Promise<IProductRefinerHierarchy[]> {\r\n let searchProductId;\r\n if (input.pageType === 'Category') {\r\n if (input.category) {\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.apiSettings.catalogId\r\n },\r\n Refinement: input.isUpdateRefinerPanel ? input.refiners : []\r\n },\r\n input.queryResultSettings,\r\n ctx\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 && ctx.requestContext.query && ctx.requestContext.query.q) {\r\n return getProductRefinerHierarchy(\r\n {\r\n SearchCondition: input.searchText,\r\n Context: {\r\n ChannelId: input.apiSettings.channelId,\r\n CatalogId: input.apiSettings.catalogId\r\n },\r\n Refinement: input.isUpdateRefinerPanel ? input.refiners : []\r\n },\r\n input.queryResultSettings,\r\n ctx\r\n );\r\n }\r\n if (input.searchText && ctx.requestContext.query && ctx.requestContext.query.productId) {\r\n const searchObject = JSON.parse(input.searchText);\r\n searchProductId = Number(searchObject.ProductId);\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 return getProductRefinerHierarchy(\r\n {\r\n Context: {\r\n ChannelId: input.apiSettings.channelId,\r\n CatalogId: input.apiSettings.catalogId\r\n },\r\n Refinement: input.isUpdateRefinerPanel ? input.refiners : [],\r\n RecommendationListId: searchObject.Recommendation,\r\n Ids: [searchProductId || DefaultValues.defaultProductIdValue]\r\n },\r\n input.queryResultSettings,\r\n ctx\r\n );\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: <IAction<IProductRefinerHierarchy[]>>action,\r\n input: createInput\r\n});\r\n\r\nexport default actionDataAction;\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt 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 { IActionContext } from '@msdyn365-commerce/core';\r\nimport { IQueryResultSettings, ProductRefiner, ProductSearchCriteria } from '@msdyn365-commerce/retail-proxy';\r\nimport { getProductSearchRefinersAsync } from '@msdyn365-commerce/retail-proxy/dist/DataActions/ProductsDataActions.g';\r\n\r\n/**\r\n * Uses Bulk refiner API to get refiners and child refiner values.\r\n * @param searchCriteria Product search criteria.\r\n * @param maxItems Max items.\r\n * @param queryResultSettings\r\n * @param ctx Action context.\r\n */\r\nexport async function getProductRefinerHierarchy(\r\n searchCriteria: ProductSearchCriteria,\r\n queryResultSettings: IQueryResultSettings,\r\n ctx: IActionContext\r\n): Promise<IProductRefinerHierarchy[]> {\r\n return getProductSearchRefinersAsync({ callerContext: ctx, queryResultSettings }, searchCriteria).then(\r\n (productRefiners: ProductRefiner[]) => {\r\n if (!productRefiners) {\r\n ctx.trace('[getRefinersByCriteriaAction] returned no refiners');\r\n return <IProductRefinerHierarchy[]>[];\r\n }\r\n\r\n const result = (productRefiners || []).map((productRefiner: ProductRefiner) => <IProductRefinerHierarchy>productRefiner);\r\n\r\n if (result.length === 0) {\r\n ctx.trace('[getRefinersByCriteriaAction] returned no IProductRefinerHierarchy objects');\r\n return <IProductRefinerHierarchy[]>[];\r\n }\r\n\r\n return result;\r\n }\r\n );\r\n}\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { ITelemetryContent } from '@msdyn365-commerce-modules/utilities';\r\nimport { IProductsDimensionsAvailabilities } from '@msdyn365-commerce/commerce-entities';\r\nimport { ICoreContext, IImageSettings } from '@msdyn365-commerce/core';\r\nimport { ProductSearchResult, ProductWarehouseInventoryAvailability, DiscountLine, CommerceList } from '@msdyn365-commerce/retail-proxy';\r\nimport { ArrayExtensions } from '@msdyn365-commerce-modules/retail-actions';\r\nimport {\r\n getDeliveryOptionsAsync,\r\n getEstimatedAvailabilityAsync\r\n} from '@msdyn365-commerce/retail-proxy/dist/DataActions/ProductsDataActions.g';\r\nimport React, { useState, useEffect } from 'react';\r\nimport { ProductComponent } from '../../../themes/dobbies/views/components/product.component';\r\nimport {\r\n IDobbiesSearchResultContainerResources,\r\n IDobbiesSearchResultContainerConfig\r\n} from '../dobbies-search-result-container.props.autogenerated';\r\n\r\ninterface IProductSearchResultItems {\r\n products: ProductSearchResult[];\r\n context: ICoreContext;\r\n resources: IDobbiesSearchResultContainerResources;\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 channelInventoryConfigurationId?: number;\r\n isPriceMinMaxEnabled?: boolean;\r\n productsDimensionAvailabilities?: IProductsDimensionsAvailabilities[][];\r\n discountLines?: (DiscountLine[] | undefined)[];\r\n config?: IDobbiesSearchResultContainerConfig;\r\n showProdPrice?: boolean;\r\n wishlists: CommerceList[] | undefined;\r\n isMobile?: boolean;\r\n}\r\n\r\nexport interface IProductWithModes extends ProductSearchResult {\r\n isCnC: boolean;\r\n isHomeDelivery: boolean;\r\n clubPlusBanner?: boolean;\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 * @returns The inventory label.\r\n */\r\nfunction getInventoryLabel(channelInventoryConfigurationId: number | undefined, product: ProductSearchResult): string | undefined {\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\nexport const ProductSearchResultItems: React.FC<IProductSearchResultItems> = ({\r\n products,\r\n context,\r\n imageSettings,\r\n resources,\r\n moduleType,\r\n moduleId,\r\n allowBackNavigation,\r\n telemetryContent,\r\n quickviewSlot,\r\n channelInventoryConfigurationId,\r\n isPriceMinMaxEnabled,\r\n isMobile,\r\n wishlists,\r\n discountLines,\r\n config,\r\n showProdPrice\r\n}) => {\r\n /* Defaulting to show false on both icons while we load the API */\r\n const productWithTempDeliveryModes = products.map(prod => {\r\n return { ...prod, isCnC: false, isHomeDelivery: false, clubPlusBanner: false };\r\n });\r\n\r\n const [productsWithDelivery, setProductsWithDelivery] = useState(productWithTempDeliveryModes);\r\n const {\r\n requestContext: {\r\n app: {\r\n config: { fulfillmentAttributeName, fulfillmentAttributeTextValue }\r\n }\r\n }\r\n } = context.actionContext;\r\n\r\n /* VSI Customization - START 14/10/2021 - Method to get Delivery Options and check availability of plant and non plant products */\r\n // @ts-ignore\r\n const getDeliveries = async () => {\r\n const attributeName = fulfillmentAttributeName\r\n ? fulfillmentAttributeName\r\n .toString()\r\n .toLowerCase()\r\n .trim()\r\n : 'fulfillmenttype';\r\n const attributeTextValue = fulfillmentAttributeTextValue\r\n ? fulfillmentAttributeTextValue\r\n .toString()\r\n .toLowerCase()\r\n .trim()\r\n : 'plants';\r\n\r\n const plantProducts: ProductSearchResult[] = [];\r\n const nonPlantProducts: ProductSearchResult[] = [];\r\n\r\n products.map(product => {\r\n const fulfillmentTypeAttribute =\r\n product.AttributeValues &&\r\n product.AttributeValues.find(attribute => {\r\n return attribute?.Name?.toLowerCase() === attributeName;\r\n });\r\n const isPlantFulfillment = fulfillmentTypeAttribute && fulfillmentTypeAttribute.TextValue?.toLowerCase() === attributeTextValue;\r\n const isPlantCategory = isPlantFulfillment ? true : false;\r\n\r\n if (isPlantCategory) {\r\n plantProducts.push(product);\r\n } else {\r\n nonPlantProducts.push(product);\r\n }\r\n });\r\n\r\n const prodIds = products.map(prod => prod.RecordId);\r\n\r\n // If there are no products, do not make any api calls\r\n if (prodIds.length <= 0) return;\r\n\r\n const deliveryOptions = await getDeliveryOptionsAsync({ callerContext: context.actionContext, queryResultSettings: {} }, prodIds);\r\n\r\n // Plants API since the warehouse storage is different\r\n const productAvailabilitesPlants = await getEstimatedAvailabilityAsync(\r\n { callerContext: context.actionContext },\r\n { ProductIds: prodIds, DefaultWarehouseOnly: false, FilterByChannelFulfillmentGroup: true }\r\n );\r\n\r\n const productsWithPlantsDelivery: IProductWithModes[] = await Promise.all(\r\n plantProducts.map(async prod => {\r\n let isCnC = false;\r\n let isHomeDelivery = false;\r\n\r\n if (productAvailabilitesPlants && productAvailabilitesPlants.ProductWarehouseInventoryAvailabilities) {\r\n productAvailabilitesPlants.ProductWarehouseInventoryAvailabilities?.map(\r\n (item: ProductWarehouseInventoryAvailability) => {\r\n if (item.InventLocationId === 'P001') {\r\n if (item.PhysicalAvailableInventoryLevelCode !== 'OOS') {\r\n isHomeDelivery = true;\r\n }\r\n } else {\r\n if (item.PhysicalAvailableInventoryLevelCode !== 'OOS') {\r\n deliveryOptions\r\n .find(option => option.ProductId === prod.RecordId)\r\n ?.DeliveryOptions?.map(option => {\r\n if (option.Code === 'ClickCol') {\r\n isCnC = true;\r\n }\r\n });\r\n }\r\n }\r\n }\r\n );\r\n }\r\n\r\n // If product has vendorship === \"yes\" then show it as available\r\n const isVendorShipAttribute = prod.AttributeValues?.find(attribute => {\r\n const attributeName = attribute.Name && attribute.Name.trim().toLowerCase();\r\n return attributeName === 'isvendershipproduct';\r\n });\r\n\r\n if (isVendorShipAttribute && isVendorShipAttribute.TextValue && isVendorShipAttribute.TextValue.toLowerCase() === 'yes') {\r\n isHomeDelivery = true;\r\n isCnC = false;\r\n }\r\n\r\n return { ...prod, isHomeDelivery, isCnC };\r\n })\r\n );\r\n\r\n // Not Plants API since the warehouse storage is different\r\n const productAvailabilitesNonPlantsHD = await getEstimatedAvailabilityAsync(\r\n { callerContext: context.actionContext },\r\n { ProductIds: prodIds, DefaultWarehouseOnly: true, FilterByChannelFulfillmentGroup: false }\r\n );\r\n const productAvailabilitesNonPlantsCNC = await getEstimatedAvailabilityAsync(\r\n { callerContext: context.actionContext },\r\n { ProductIds: prodIds, DefaultWarehouseOnly: false, FilterByChannelFulfillmentGroup: true }\r\n );\r\n\r\n const productsWithNonPlantsDelivery: IProductWithModes[] = await Promise.all(\r\n nonPlantProducts.map(async prod => {\r\n let isCnC = false;\r\n let isHomeDelivery = false;\r\n\r\n if (productAvailabilitesNonPlantsHD && productAvailabilitesNonPlantsHD.AggregatedProductInventoryAvailabilities) {\r\n productAvailabilitesNonPlantsHD.AggregatedProductInventoryAvailabilities.map(stores => {\r\n if (stores.ProductId === prod.RecordId && stores.PhysicalAvailableInventoryLevelCode !== 'OOS') {\r\n isHomeDelivery = true;\r\n }\r\n });\r\n }\r\n\r\n if (productAvailabilitesNonPlantsCNC && productAvailabilitesNonPlantsCNC.AggregatedProductInventoryAvailabilities) {\r\n productAvailabilitesNonPlantsCNC.AggregatedProductInventoryAvailabilities.map(stores => {\r\n if (stores.ProductId === prod.RecordId && stores.PhysicalAvailableInventoryLevelCode !== 'OOS') {\r\n deliveryOptions\r\n .find(option => option.ProductId === prod.RecordId)\r\n ?.DeliveryOptions?.map(option => {\r\n if (option.Code === 'ClickCol') {\r\n isCnC = true;\r\n }\r\n });\r\n }\r\n });\r\n }\r\n\r\n // If product has vendorship === \"yes\" then show it as available\r\n const isVendorShipAttribute = prod.AttributeValues?.find(attribute => {\r\n const attributeName = attribute.Name && attribute.Name.trim().toLowerCase();\r\n return attributeName === 'isvendershipproduct';\r\n });\r\n\r\n if (isVendorShipAttribute && isVendorShipAttribute.TextValue && isVendorShipAttribute.TextValue.toLowerCase() === 'yes') {\r\n isHomeDelivery = true;\r\n isCnC = false;\r\n }\r\n\r\n return { ...prod, isHomeDelivery, isCnC };\r\n })\r\n );\r\n\r\n const totalProducts = [...productsWithPlantsDelivery, ...productsWithNonPlantsDelivery];\r\n const allProducts: any = [];\r\n products.map(prod => {\r\n totalProducts.find(item => {\r\n if (item.RecordId === prod.RecordId) {\r\n allProducts.push(item);\r\n }\r\n });\r\n });\r\n setProductsWithDelivery(allProducts);\r\n };\r\n\r\n useEffect(() => {\r\n const productWithTempDeliveryModes = products.map(prod => {\r\n return { ...prod, isCnC: false, isHomeDelivery: false, clubPlusBanner: false };\r\n });\r\n\r\n setProductsWithDelivery(productWithTempDeliveryModes);\r\n //getDeliveries();\r\n }, [products]);\r\n\r\n const showClubPlusBanner = (prodId: number): void => {\r\n const newArr = [...productsWithDelivery];\r\n newArr &&\r\n newArr.map(val => {\r\n if (val.RecordId === prodId) {\r\n val.clubPlusBanner = true;\r\n } else {\r\n val.clubPlusBanner = false;\r\n }\r\n });\r\n setProductsWithDelivery(newArr);\r\n };\r\n\r\n const hideClubPlusBanner = (prodId: number): void => {\r\n const newArr = [...productsWithDelivery];\r\n newArr &&\r\n newArr.map(val => {\r\n if (val.RecordId === prodId) {\r\n val.clubPlusBanner = false;\r\n }\r\n });\r\n setProductsWithDelivery(newArr);\r\n };\r\n\r\n /* VSI Customization - END */\r\n\r\n const productClass = 'ms-product-search-result__item';\r\n return (\r\n <ul className='list-unstyled'>\r\n {productsWithDelivery &&\r\n productsWithDelivery.map((product: IProductWithModes, index: number) => {\r\n return (\r\n <li className={productClass} key={index}>\r\n <ProductComponent\r\n context={context}\r\n telemetryContent={telemetryContent}\r\n imageSettings={imageSettings}\r\n freePriceText={resources.priceFree}\r\n originalPriceText={resources.originalPriceText}\r\n currentPriceText={resources.currentPriceText}\r\n ratingAriaLabel={resources.ratingAriaLabel}\r\n allowBack={allowBackNavigation}\r\n id={moduleId}\r\n typeName={moduleType}\r\n data={{ product: product }}\r\n inventoryLabel={getInventoryLabel(channelInventoryConfigurationId, product)}\r\n discountLine={discountLines && discountLines.length > 0 ? discountLines[index] : []}\r\n badgeLink={config && config.clubPlusBadgeLink}\r\n showProdPrice={showProdPrice}\r\n showBanner={showClubPlusBanner}\r\n hideBanner={hideClubPlusBanner}\r\n quickViewButton={quickviewSlot}\r\n wishlists={wishlists}\r\n isMobile={isMobile}\r\n />\r\n </li>\r\n );\r\n })}\r\n </ul>\r\n );\r\n};\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\n/* eslint-disable no-duplicate-imports */\r\n\r\nimport { ITelemetry } from '@msdyn365-commerce/core';\r\nimport { AttributeDataType, ProductRefinerValue, RefinerType } from '@msdyn365-commerce/retail-proxy';\r\n\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\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 (\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 * 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(productRefinerValue: ProductRefinerValue, refinementCriterion: ProductRefinerValue): boolean {\r\n // If the value is a range, then match only on data type value; otherwise match on item string\r\n return (\r\n refinementCriterion.RefinerRecordId === productRefinerValue.RefinerRecordId &&\r\n refinementCriterion.RefinerSourceValue === productRefinerValue.RefinerSourceValue &&\r\n refinementCriterion.DataTypeValue === productRefinerValue.DataTypeValue &&\r\n (isRangeType(refinementCriterion.DataTypeValue) ||\r\n refinementCriterion.LeftValueBoundString === productRefinerValue.LeftValueBoundString)\r\n );\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 currentRefinementCriteria.forEach((selectedCriterion: ProductRefinerValue) => {\r\n if (isMatchingRefinementCriterion(itemToggleNotification.productRefinerValue, selectedCriterion)) {\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)\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\n// VSI CUSTOMIZATION - START - Format Price Slider to 2 fixed decimal points\r\nexport function formatPriceSlider(\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: currency,\r\n minimumFractionDigits: 2\r\n }).format(priceAmount);\r\n } catch (e) {\r\n result = `${priceAmount} ${currency}`;\r\n telemetry.warning(`[refine-menu.utilities.formatPrice] Failed to format price for ${result}: ${e}`);\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// VSI CUSTOMIZATION - END\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt 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<IRangeRefineItemProps, IRangeRefineItemState> {\r\n private readonly _formattedPriceReverseLookup: Map<string, string> = new Map();\r\n\r\n private readonly minInput: React.RefObject<HTMLInputElement>;\r\n\r\n private readonly maxInput: React.RefObject<HTMLInputElement>;\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<HTMLInputElement>();\r\n this.maxInput = React.createRef<HTMLInputElement>();\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 <form className='ms-refine-submenu__input-range-refiner' {...formAttrs}>\r\n <label className={minLabelClassName}>\r\n {refineItemCommonProps.minLabel}\r\n <input\r\n className={minInputClassName}\r\n onChange={this._changeMin}\r\n onFocus={this._changeMin}\r\n onBlur={this._finishChangeMin}\r\n value={formattedSelectedMin}\r\n ref={this.minInput}\r\n />\r\n </label>\r\n <label className={maxLabelClassName}>\r\n {refineItemCommonProps.maxLabel}\r\n <input\r\n className={maxInputClassName}\r\n placeholder={formattedSelectedMax ? undefined : refineItemCommonProps.placeholderTextMax}\r\n onChange={this._changeMax}\r\n onFocus={this._changeMax}\r\n onBlur={this._finishChangeMax}\r\n value={formattedSelectedMax}\r\n ref={this.maxInput}\r\n />\r\n </label>\r\n {validationErrorMin && (\r\n <span className='ms-refine-submenu__input-range-error-text refine-submenu__input-range-min-error-text'>\r\n {validationErrorMin}\r\n </span>\r\n )}\r\n {validationErrorMax && validationErrorMin !== validationErrorMax && (\r\n <span className='ms-refine-submenu__input-range-error-text refine-submenu__input-range-max-error-text'>\r\n {validationErrorMax}\r\n </span>\r\n )}\r\n </form>\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 <Slider\r\n className='ms-refine-submenu__range-refiner'\r\n key={this.state.sliderId}\r\n sliderKey={sliderKey}\r\n id={this.state.sliderId}\r\n inForm={false}\r\n min={(this.state.minValue && Number(this.state.minValue)) || undefined}\r\n max={(this.state.maxValue && Number(this.state.maxValue)) || undefined}\r\n step={1}\r\n orientation='horizontal'\r\n labels={this.state.labels}\r\n showLabels\r\n showTooltip\r\n sliderThumbs={this.state.sliderThumbs}\r\n onChangeEnd={this._onRangeUpdateEnd}\r\n onChange={debounce(this._onRangeUpdate, 500)}\r\n handleTooltipText={this._handleRangeTooltipText}\r\n {...ariaAttributes}\r\n />\r\n );\r\n }\r\n\r\n private _changeMin(event: React.FocusEvent<HTMLInputElement>): void {\r\n this._changeValue(event, 'Min');\r\n }\r\n\r\n private _changeMax(event: React.FocusEvent<HTMLInputElement>): void {\r\n this._changeValue(event, 'Max');\r\n }\r\n\r\n private _changeValue(event: React.FocusEvent<HTMLInputElement>, 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<HTMLInputElement>): 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<HTMLInputElement>): 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 const result = this.props.context.cultureFormatter.formatCurrency(Number(amount), this.currencyCode);\r\n return result;\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 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 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 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","const binding = { modules: {}, dataActions: {} };\n\n const registerActionId = (actionPath) => {\n if (binding.dataActions[actionPath] &&\n binding.dataActions[actionPath].default &&\n binding.dataActions[actionPath].default.prototype &&\n binding.dataActions[actionPath].default.prototype.id) {\n binding.dataActions[binding.dataActions[actionPath].default.prototype.id] = binding.dataActions[actionPath];\n } else {\n Object.keys(binding.dataActions[actionPath] || {}).forEach(exportName => {\n if (binding.dataActions[actionPath][exportName] &&\n binding.dataActions[actionPath][exportName].prototype &&\n binding.dataActions[actionPath][exportName].prototype.Action) {\n binding.dataActions[binding.dataActions[actionPath][exportName].prototype.id] = binding.dataActions[actionPath][exportName];\n }\n })\n }\n };\n\n const registerSanitizedActionPath = (sanitizedActionPath, dataAction) => {\n if (process.env.NODE_ENV === 'development') {\n if (!dataAction.default) {\n throw new Error('Data action path does not have a default export');\n }\n if (!(dataAction.default.prototype.id && binding.dataActions[dataAction.default.prototype.id]) || !binding.dataActions[sanitizedActionPath]) {\n binding.dataActions[sanitizedActionPath] = dataAction;\n }\n } else {\n binding.dataActions[sanitizedActionPath] = dataAction;\n if (!binding.dataActions[sanitizedActionPath].default) {\n throw new Error('Data action path ' + sanitizedActionPath + ' does not have a default export');\n }\n binding.dataActions[sanitizedActionPath].default.prototype.RegistrationId = sanitizedActionPath;\n if (binding.dataActions[sanitizedActionPath].default.prototype.id) {\n binding.dataActions[binding.dataActions[sanitizedActionPath].default.prototype.id] = sanitizedActionPath;\n }\n }\n };\n \n\n (binding.modules['dobbies-search-result-container'] = {\n c: () => require('partner/modules/dobbies-search-result-container/dobbies-search-result-container.tsx'),\n $type: 'containerModule',\n da: [{name:'category', path:'@msdyn365-commerce-modules/retail-actions/dist/lib/get-current-category', runOn: 0},{name:'categoryHierarchy', path:'@msdyn365-commerce-modules/retail-actions/dist/lib/get-current-category-hierarchy', runOn: 0},{name:'featureProduct', path:'@msdyn365-commerce-modules/retail-actions/dist/lib/get-selected-variant', runOn: 0},{name:'featureState', path:'@msdyn365-commerce-modules/retail-actions/dist/lib/get-feature-state', runOn: 0},{name:'listPageState', path:'modules/dobbies-search-result-container/list-page-state', runOn: 0},{name:'modulesSharedState', path:'themes/dobbies/actions/modules-state-share-action', runOn: 0},{name:'products', path:'modules/dobbies-search-result-container/actions/get-full-products-by-collection', runOn: 0},{name:'refiners', path:'modules/dobbies-search-result-container/actions/get-refiners-for-collection', runOn: 0},{name:'searchConfiguration', path:'modules/dobbies-search-result-container/actions/get-mapped-search-configuration', runOn: 0},{name:'wishlists', path:'@msdyn365-commerce-modules/retail-actions/dist/lib/get-wishlist-by-customer-id', runOn: 1}],\n \n iNM: false,\n ns: '__local__',\n n: 'dobbies-search-result-container',\n p: '__local__',\n \n pdp: '',\n \n \n md: 'src/modules/dobbies-search-result-container'\n });\n \n\n {\n const sanitizedActionPath = '@msdyn365-commerce-modules/retail-actions/dist/lib/get-current-category';\n let dataAction = require('@msdyn365-commerce-modules/retail-actions/dist/lib/get-current-category');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n {\n const sanitizedActionPath = '@msdyn365-commerce-modules/retail-actions/dist/lib/get-current-category-hierarchy';\n let dataAction = require('@msdyn365-commerce-modules/retail-actions/dist/lib/get-current-category-hierarchy');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n {\n const sanitizedActionPath = '@msdyn365-commerce-modules/retail-actions/dist/lib/get-feature-state';\n let dataAction = require('@msdyn365-commerce-modules/retail-actions/dist/lib/get-feature-state');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n {\n const sanitizedActionPath = '@msdyn365-commerce-modules/retail-actions/dist/lib/get-selected-variant';\n let dataAction = require('@msdyn365-commerce-modules/retail-actions/dist/lib/get-selected-variant');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n {\n const sanitizedActionPath = '@msdyn365-commerce-modules/retail-actions/dist/lib/get-wishlist-by-customer-id';\n let dataAction = require('@msdyn365-commerce-modules/retail-actions/dist/lib/get-wishlist-by-customer-id');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n {\n const sanitizedActionPath = 'modules/dobbies-search-result-container/actions/get-full-products-by-collection';\n let dataAction = require('partner/modules/dobbies-search-result-container/actions/get-full-products-by-collection');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n {\n const sanitizedActionPath = 'modules/dobbies-search-result-container/actions/get-mapped-search-configuration';\n let dataAction = require('partner/modules/dobbies-search-result-container/actions/get-mapped-search-configuration');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n {\n const sanitizedActionPath = 'modules/dobbies-search-result-container/actions/get-refiners-for-collection';\n let dataAction = require('partner/modules/dobbies-search-result-container/actions/get-refiners-for-collection');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n {\n const sanitizedActionPath = 'modules/dobbies-search-result-container/list-page-state';\n let dataAction = require('partner/modules/dobbies-search-result-container/list-page-state');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n {\n const sanitizedActionPath = 'themes/dobbies/actions/modules-state-share-action';\n let dataAction = require('partner/themes/dobbies/actions/modules-state-share-action');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n \n window.__bindings__ = window.__bindings__ || {};\n window.__bindings__.modules = {\n ...window.__bindings__.modules || {},\n ...binding.modules\n };\n \n window.__bindings__.dataActions = {\n ...window.__bindings__.dataActions || {},\n ...binding.dataActions\n };\n export const viewDictionary = {};\n viewDictionary['__local__|__local__|modules|dobbies-search-result-container|dobbies-search-result-container'] = {\n c: () => require('partner/modules/dobbies-search-result-container/dobbies-search-result-container.view.tsx'),\n cn: '__local__-__local__-dobbies-search-result-container'\n };\nwindow.__bindings__ = window.__bindings__ || {};\nwindow.__bindings__.viewDictionary = {\n ...window.__bindings__.viewDictionary || {},\n ...viewDictionary\n };","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { Module, Node } from '@msdyn365-commerce-modules/utilities';\r\nimport React, { useEffect, useState } from 'react';\r\nimport { ModulesStateShareInput } from '../../themes/dobbies/actions/modules-state-share-action';\r\nimport DobbiesModal from '../../themes/dobbies/views/custom-components/dobbies-modal';\r\nimport { ISearchResultModalViewProps } from './components';\r\nimport {\r\n ICategoryHierarchyViewProps,\r\n IRefineMenuViewProps,\r\n ISearchResultContainerViewProps,\r\n ISortByViewProps,\r\n ITitleViewProps\r\n} from './dobbies-search-result-container';\r\n\r\nconst SearchResultContainerView: React.FC<ISearchResultContainerViewProps> = props => {\r\n const {\r\n data: {\r\n category: { result: currentCategory }\r\n },\r\n SearchResultContainer,\r\n products,\r\n ProductsContainer,\r\n ProductSectionContainer,\r\n choiceSummary,\r\n isMobile,\r\n modalToggle,\r\n searchResultModal,\r\n TitleViewProps,\r\n refineMenu,\r\n categoryHierarchy,\r\n sortByOptions,\r\n CategoryNavContainer,\r\n RefineAndProductSectionContainer,\r\n errorMessage,\r\n FeatureSearchContainer,\r\n similarLookProduct,\r\n slots: { browse },\r\n resources: { browseButtonText },\r\n pagination\r\n } = props;\r\n const [showModal, setShowModal] = useState(false); /* VSI-Customization -- START showModal Hook for managing state of showModal */\r\n const [categoryTitle, SetCategoryTitle] = useState<string | undefined>(); // Following hook is used to store category name\r\n const isSearchPage = props.context.request.query?.q;\r\n\r\n useEffect(() => {\r\n document.addEventListener('keydown', (e: KeyboardEvent) => {\r\n if (e.key.toLocaleLowerCase() === 'escape') {\r\n if (showModal) {\r\n setShowModal(!showModal);\r\n }\r\n }\r\n });\r\n // Store categoryName in state data action to display it in category header\r\n if (categoryTitle === undefined) {\r\n const currentCategoryName = currentCategory && currentCategory.Name ? currentCategory.Name : '';\r\n props.context.actionContext.update(new ModulesStateShareInput(), { categoryName: currentCategoryName });\r\n SetCategoryTitle(currentCategoryName);\r\n }\r\n }, [showModal]);\r\n const modalTitle = (): JSX.Element => {\r\n const { category } = props.data;\r\n const categoryName = category && category.result && category.result.Name;\r\n const handleShowModal = () => setShowModal(!showModal);\r\n return (\r\n <Node tag='div' className='view-all-popup-header'>\r\n <Node tag='span' className='title-text'>\r\n {categoryName}\r\n </Node>\r\n <div className='header-close-button' onClick={handleShowModal} role='button'>\r\n <i className='msc-modal__close-button' />\r\n </div>\r\n </Node>\r\n );\r\n };\r\n const modalFooter = (): JSX.Element => {\r\n const handleShowModal = () => setShowModal(!showModal);\r\n return <div className='close-button' role='button' onClick={handleShowModal} />;\r\n };\r\n const _modalToggle = () => {\r\n setShowModal(!showModal);\r\n };\r\n const renderToggle = (slotBrowse: React.ReactNode): JSX.Element | undefined => {\r\n const handleShowModal = () => setShowModal(!showModal);\r\n return (\r\n <>\r\n <div className='category-list-mobile'>\r\n <button onClick={handleShowModal}>{browseButtonText}</button>\r\n </div>\r\n <DobbiesModal\r\n className='modal ms-dobbies-browse'\r\n isOpen={showModal}\r\n modalBodySlots={browse}\r\n onModalToggle={_modalToggle}\r\n modalTitle={modalTitle()}\r\n modalFooter={modalFooter()}\r\n />\r\n </>\r\n );\r\n };\r\n\r\n /* VSI-Customization -- END */\r\n if (isMobile) {\r\n return (\r\n <Module {...SearchResultContainer}>\r\n {/* {renderOutOfStockBtn(props)} */}\r\n {isSearchPage && TitleViewProps && renderTitleAndProductCount(TitleViewProps)}\r\n {categoryHierarchy && renderCategoryHierarchy(categoryHierarchy)}\r\n {/* VSI-Customization -- START Render Browse Module for Mobile view */}\r\n {renderToggle(browse)}\r\n {/* VSI-Customization -- END */}\r\n {modalToggle}\r\n {choiceSummary}\r\n {createSearchResultModal(props, searchResultModal, refineMenu, sortByOptions)}\r\n <Node {...FeatureSearchContainer}>{similarLookProduct}</Node>\r\n <Node {...ProductsContainer}>\r\n {errorMessage}\r\n {products}\r\n </Node>\r\n {pagination}\r\n </Module>\r\n );\r\n }\r\n return (\r\n <Module {...SearchResultContainer}>\r\n <Node {...CategoryNavContainer}>\r\n {/* {renderOutOfStockBtn(props)} */}\r\n {/* {outOfStock && renderOOSBtn(props)} */}\r\n {categoryHierarchy && renderCategoryHierarchy(categoryHierarchy)}\r\n {isSearchPage && TitleViewProps && renderTitleAndProductCount(TitleViewProps)}\r\n </Node>\r\n <Node {...RefineAndProductSectionContainer}>\r\n {renderRefiner(refineMenu, browse)}\r\n <Node {...ProductSectionContainer}>\r\n {choiceSummary}\r\n {sortByOptions && renderSort(sortByOptions)}\r\n <Node {...FeatureSearchContainer}>{similarLookProduct}</Node>\r\n <Node {...ProductsContainer}>\r\n {errorMessage}\r\n {products}\r\n </Node>\r\n {pagination}\r\n </Node>\r\n </Node>\r\n </Module>\r\n );\r\n};\r\n\r\nconst createSearchResultModal = (\r\n oosProps: ISearchResultContainerViewProps,\r\n modalProps: ISearchResultModalViewProps,\r\n refineMenu: IRefineMenuViewProps,\r\n sortByDropDown: ISortByViewProps\r\n): JSX.Element => {\r\n return React.cloneElement(\r\n modalProps.modal,\r\n {},\r\n modalProps.modalHeader,\r\n createModalBody(oosProps, modalProps, refineMenu, sortByDropDown),\r\n modalProps.modalFooter\r\n );\r\n};\r\n\r\nconst createModalBody = (\r\n oosProps: ISearchResultContainerViewProps,\r\n props: ISearchResultModalViewProps,\r\n refineMenu: IRefineMenuViewProps,\r\n sortByDropDown: ISortByViewProps\r\n): JSX.Element | null => {\r\n if (sortByDropDown) {\r\n return React.cloneElement(props.modalBody, {}, renderSort(sortByDropDown), renderRefiner(refineMenu, null));\r\n }\r\n return null;\r\n};\r\n\r\nconst renderRefiner = (props: IRefineMenuViewProps, slotBrowse: React.ReactNode[] | null): JSX.Element | null => {\r\n const { refiners, endingRefiners, RefineMenuContainer, RefinerSectionContainer } = props;\r\n\r\n if (refiners && endingRefiners) {\r\n return (\r\n <>\r\n <br />\r\n\r\n <Node {...RefinerSectionContainer}>\r\n {refiners.map((submenu, index) => (\r\n <React.Fragment key={index}>{submenu}</React.Fragment>\r\n ))}\r\n <div className='refiner-add-remove'>\r\n <Node {...RefineMenuContainer}>\r\n <div className='category-listing'>{slotBrowse && slotBrowse}</div>\r\n\r\n {endingRefiners.map((submenu, index) => (\r\n <React.Fragment key={index}>{submenu}</React.Fragment>\r\n ))}\r\n </Node>\r\n </div>\r\n </Node>\r\n </>\r\n );\r\n }\r\n return null;\r\n};\r\n\r\nconst renderSort = (props: ISortByViewProps): JSX.Element | null => {\r\n const { SortingContainer, sortByDropDown } = props;\r\n if (sortByDropDown) {\r\n return <Node {...SortingContainer}>{sortByDropDown}</Node>;\r\n }\r\n return null;\r\n};\r\n\r\n// const renderOOSBtn = (props: ISearchResultContainerViewProps) : JSX.Element | null => {\r\n// return (\r\n// <Node className=''>\r\n// {outOfStock}\r\n// </Node>\r\n// )\r\n// }\r\n\r\n// const renderOutOfStockBtn = (props: ISearchResultContainerViewProps): JSX.Element | null => {\r\n// const {showOutOfStock,hideOutOfStock, outOfStockStatus, isMobile, resources} = props;\r\n// return (\r\n// <Node className={isMobile ? 'out-of-stock-mob-container' : 'out-of-stock-container'}>\r\n// <p className='out-of-stock-text'>{resources.outOfStockNavText}</p>\r\n// <Node className='out-of-stock-btn-container'>\r\n// <button className={outOfStockStatus ? 'out-of-stock-active' : 'out-of-stock-hide'} onClick={showOutOfStock}>{resources.showOutofStockBtn}</button>\r\n// <button className={!outOfStockStatus ? 'out-of-stock-active' : 'out-of-stock-hide'} onClick={hideOutOfStock}>{resources.hideOutOfStockBtn}</button>\r\n// </Node>\r\n// {/* <button onClick={toggleOutOfStock}>Out Of Stock</button> */}\r\n// </Node>\r\n// )\r\n// }\r\n\r\nconst renderCategoryHierarchy = (props: ICategoryHierarchyViewProps): JSX.Element | null => {\r\n const { CategoryHierarchyContainer, categoryHierarchyList, categoryHierarchySeparator } = props;\r\n if (categoryHierarchyList) {\r\n return (\r\n <Node {...CategoryHierarchyContainer}>\r\n {categoryHierarchyList.map((category, index) => (\r\n <React.Fragment key={index}>\r\n {category}\r\n {categoryHierarchyList && categoryHierarchyList[index + 1] && categoryHierarchySeparator}\r\n </React.Fragment>\r\n ))}\r\n </Node>\r\n );\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst renderTitleAndProductCount = (props: ITitleViewProps): JSX.Element | null => {\r\n const { title, TitleContainer } = props;\r\n\r\n if (title) {\r\n return (\r\n <Node {...TitleContainer}>\r\n <h2>\r\n {title.titlePrefix} {title.titleText} - {title.titleCount}\r\n </h2>\r\n </Node>\r\n );\r\n }\r\n return null;\r\n};\r\n\r\nexport default SearchResultContainerView;\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\n/* eslint-disable no-duplicate-imports */\r\n\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, ITelemetryContent } from '@msdyn365-commerce-modules/utilities';\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<IGeneric<IAny>>;\r\n moduleId: string;\r\n moduleTypeName: string;\r\n productCountAriaLabel?: string;\r\n singleProductCountAriaLabel?: string;\r\n isMobile?: boolean;\r\n\r\n /**\r\n * The telemetry content\r\n */\r\n telemetryContent?: ITelemetryContent;\r\n onUpdateRefiners(notfication: Readonly<IRefineItemToggleNotification>): 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<IRefineSubmenuProps>}\r\n */\r\nclass RefineSubmenu extends React.Component<IRefineSubmenuProps, IRefineSubmenuState> {\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 expanded: true\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 // VSI CUSTOMIZATION START\r\n const currentUrl = this.props.context.request.url.requestUrl.pathname;\r\n if (currentUrl.includes('edits')) {\r\n if (productRefinerHierarchy.KeyName === 'Category') {\r\n return null;\r\n }\r\n } else {\r\n if (productRefinerHierarchy.KeyName === 'Categories') {\r\n return null;\r\n }\r\n }\r\n // VSI CUSTOMIZATION END\r\n return (\r\n <div className={`ms-refine-submenu list-group ${productRefinerHierarchy.KeyName}`}>\r\n <Button\r\n className={this.state.expanded ? 'ms-refine-submenu__toggle_collapsed' : 'ms-refine-submenu__toggle_expanded'}\r\n aria-label={productRefinerHierarchy.KeyName || 'refiner.Name'}\r\n onClick={this._onToggleSubmenu}\r\n aria-expanded={this.state.expanded}\r\n >\r\n {productRefinerHierarchy.KeyName}\r\n </Button>\r\n <div className={this.state.expanded ? 'slide-up' : 'slide-down'}>{this._renderChildItems(productRefinerHierarchy)}</div>\r\n </div>\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 { isDisabled, refineItemCommonProps, selectedRefinerValues, context } = this.props;\r\n const isSingleSelect =\r\n productRefinerHierarchy.RefinerTypeValue === RefinerType.SingleSelect &&\r\n productRefinerHierarchy.SourceValue === ProductRefinerSource.Rating;\r\n const role = isSingleSelect ? { role: 'radiogroup' } : undefined;\r\n let refinerValuesList = productRefinerHierarchy.Values || [];\r\n if (productRefinerHierarchy && productRefinerHierarchy.Values && productRefinerHierarchy?.Values?.length > 0) {\r\n refinerValuesList = productRefinerHierarchy!.Values!.sort((a, b) =>\r\n a!.LeftValueBoundString!.localeCompare(b!.LeftValueBoundString!)\r\n );\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\r\n const selectedRefinementCriterion = findMatchingRefinementCriterion(child, selectedRefinerValues);\r\n\r\n return (\r\n <RefineItem\r\n parentProductRefinerHierarchy={productRefinerHierarchy}\r\n productRefinerValue={child}\r\n selectedRefinementCriterion={selectedRefinementCriterion}\r\n selectedRefinerValues={selectedRefinerValues.filter(selectedValue =>\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 />\r\n );\r\n });\r\n return (\r\n <ul\r\n className={`ms-refine-submenu__list ${productRefinerHierarchy.KeyName}`}\r\n {...role}\r\n aria-label={productRefinerHierarchy.KeyName}\r\n >\r\n {listItems}\r\n </ul>\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 <li className={`${submenuClassNamePrefix}--range`} key={index}>\r\n <RangeRefineItem\r\n parentProductRefinerHierarchy={productRefinerHierarchy}\r\n productRefinerValue={child}\r\n selectedRefinementCriterion={selectedRefinementCriterion}\r\n refineItemCommonProps={refineItemCommonProps}\r\n onToggle={this._onToggleItem}\r\n urlBuilder={this.props.urlBuilder}\r\n isDisabled={isDisabled}\r\n rangeType={rangeType}\r\n key={key}\r\n sliderKey={key}\r\n context={context}\r\n minValueSliderThumbAriaLabel={minValueSliderThumbAriaLabel}\r\n maxValueSliderThumbAriaLabel={maxValueSliderThumbAriaLabel}\r\n moduleId={this.props.moduleId}\r\n moduleTypeName={this.props.moduleTypeName}\r\n />\r\n </li>\r\n );\r\n });\r\n return <ul className={`ms-refine-submenu__list list-unstyled ${productRefinerHierarchy.KeyName}`}>{listItems}</ul>;\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","module.exports = React;","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt 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 ICreateActionContext,\r\n IGeneric\r\n} from '@msdyn365-commerce/core';\r\nimport { ProductRefinerValue, ProductSearchResult, SimpleProduct, SortingInfo } from '@msdyn365-commerce/retail-proxy';\r\nimport { observable } from 'mobx';\r\n\r\nimport { listPageType } from './actions';\r\n\r\n/**\r\n * ListPageState class\r\n */\r\nexport class ListPageState {\r\n @observable public activeFilters: ProductRefinerValue[] | null = null;\r\n @observable public activeProducts: ProductSearchResult[] = [];\r\n @observable public sortingCritera: SortingInfo | null = null;\r\n @observable public currentPageNumber: number | null = null;\r\n @observable public totalProductCount: number | undefined;\r\n @observable public pageSize: number = 10;\r\n @observable public pageType: listPageType = 'Unknown';\r\n @observable public featureProduct: SimpleProduct | null = null;\r\n}\r\n\r\n/**\r\n * ListPageStateInput - action input\r\n */\r\nexport class ListPageStateInput implements IActionInput {\r\n public getCacheKey = () => `ListPageState`;\r\n public getCacheObjectType = () => 'ListPageState';\r\n public dataCacheType = (): CacheType => 'request';\r\n}\r\n\r\nexport async function listPageStateAction(\r\n input: ListPageStateInput,\r\n ctx: IActionContext\r\n): Promise<ListPageState> {\r\n return new ListPageState();\r\n}\r\n\r\n/**\r\n * create new input for create action\r\n */\r\nexport const createListPageInput = (\r\n inputData: ICreateActionContext<IGeneric<IAny>>\r\n): IActionInput => {\r\n return new ListPageStateInput();\r\n};\r\n\r\n/**\r\n * ListPageState - create action\r\n */\r\nexport default createObservableDataAction<ListPageState>({\r\n action: <IAction<ListPageState>>listPageStateAction,\r\n input: createListPageInput\r\n});\r\n","/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License. See License.txt in the project root for license information.\r\n *--------------------------------------------------------------------------------------------*/\r\nimport {\r\n CacheType, createObservableDataAction, IAction, IActionContext,\r\n IActionInput, IAny, ICreateActionContext, IGeneric\r\n} from '@msdyn365-commerce/core';\r\n\r\n/**\r\n * LoyaltyCardState Input Action\r\n */\r\n\r\nexport class ModulesStateShareInput implements IActionInput {\r\n // TODO: Determine if the results of this get action should cache the results and if so provide\r\n // a cache object type and an appropriate cache key\r\n public getCacheKey = () => `modulesSharedState`;\r\n public getCacheObjectType = () => 'modulesSharedState';\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 IModulesSharedState {\r\n customerLoyaltyTierId: string | undefined;\r\n categoryName: string | undefined;\r\n}\r\n\r\n/**\r\n * TODO: Use this function to create the input required to make the action call\r\n */\r\nconst createInput = (inputData: ICreateActionContext<IGeneric<IAny>>): IActionInput => {\r\n return new ModulesStateShareInput();\r\n};\r\n/**\r\n * TODO: Use this function to call your action and process the results as needed\r\n */\r\nexport async function sampleStateAction(input: ModulesStateShareInput, ctx: IActionContext): Promise<IModulesSharedState> {\r\n return { customerLoyaltyTierId: undefined, categoryName: undefined };\r\n}\r\n\r\n/**\r\n * SampleState - create action\r\n */\r\nexport default createObservableDataAction<IModulesSharedState>({\r\n action: <IAction<IModulesSharedState>>sampleStateAction,\r\n input: createInput\r\n});","module.exports = ReactDOM;","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { getFallbackImageUrl, getProductPageUrlSync } from '@msdyn365-commerce-modules/retail-actions';\r\nimport { getPayloadObject, getTelemetryAttributes, ITelemetryContent ,onTelemetryClick } from '@msdyn365-commerce-modules/utilities';\r\nimport { ICoreContext, IGridSettings, IImageData, IImageSettings, Image} from '@msdyn365-commerce/core';\r\nimport { SimpleProduct } from '@msdyn365-commerce/retail-proxy';\r\nimport * as React from 'react';\r\nimport { IDobbiesSearchResultContainerResources } from '../dobbies-search-result-container.props.autogenerated';\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: IDobbiesSearchResultContainerResources;\r\n imageSettings?: IImageSettings;\r\n moduleType: string;\r\n moduleId: string;\r\n telemetryContent?: ITelemetryContent;\r\n}\r\n\r\nexport const FeatureSearchResultItem: React.FC<IFeatureSearchResultItem> = ({\r\n product,\r\n context,\r\n imageSettings,\r\n resources,\r\n telemetryContent\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(product.ItemId, context.actionContext.requestContext.apiSettings);\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 <div className='ms-feature-search-result__item'>\r\n <a href={productUrl} onClick={onTelemetryClick(telemetryContent!, payLoad, product.Name!)}{...attribute} aria-label={product.Name}>\r\n <div className='msc-feature-search-result__item__image'>\r\n {renderProductPlacementImage(imageSettings, context.request.gridSettings, product.PrimaryImageUrl, product.Name, fallbackImage)}\r\n </div>\r\n </a>\r\n <div className='msc-feature-search-result__item__detail'>\r\n <p className='msc-feature-search-result__item__heading'>{resources.featureSimilarLooksTitle}</p>\r\n {renderProductTitle(product?.Name)}\r\n </div>\r\n </div>\r\n );\r\n\r\n};\r\n\r\nfunction renderProductPlacementImage(imageSettings?: IImageSettings, gridSettings?: IGridSettings, imageUrl?: string, altText?: string, fallbackImage?: string,): 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: gridSettings,\r\n imageSettings: imageSettings,\r\n fallBackSrc: fallbackImage\r\n };\r\n return (\r\n <Image {...img} {...imageProps} loadFailureBehavior='empty' />\r\n );\r\n}\r\n\r\nfunction renderProductTitle(title?: string): JSX.Element | null {\r\nreturn <h1 className='msc-feature-search-result__item__product-title'>{title}</h1>;\r\n}","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport MsDyn365, {\r\n CacheType,\r\n createObservableDataAction,\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 { searchByCriteriaAsync } from '@msdyn365-commerce/retail-proxy/dist/DataActions/ProductsDataActions.g';\r\nimport { getInventoryConfigurationAsync } from '@msdyn365-commerce/retail-proxy/dist/DataActions/StoreOperationsDataActions.g';\r\nimport { ArrayExtensions, generateProductImageUrl, InventoryLevels, ObjectExtensions } from '@msdyn365-commerce-modules/retail-actions';\r\n\r\nimport { ListPageStateInput } from '../list-page-state';\r\nimport { BaseCollectionInput, createBaseCollectionInput } from './base-collection-action';\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 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: ProductSearchResult[];\r\n count: number;\r\n channelInventoryConfigurationId?: 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 * Finds whether a product is out of stock based on the attribute.\r\n * @param product - The product.\r\n * @param channelInventoryConfiguration - The channel configuration.\r\n * @returns True if is OOS, false otherwise.\r\n */\r\nfunction isOutOfStock(product: ProductSearchResult, channelInventoryConfiguration: ChannelInventoryConfiguration): boolean {\r\n if (!ArrayExtensions.hasElements(product.AttributeValues)) {\r\n // If no attributes then assume is in stock\r\n return false;\r\n }\r\n for (const attribute of product.AttributeValues) {\r\n if (\r\n attribute.RecordId === channelInventoryConfiguration.InventoryProductAttributeRecordId &&\r\n attribute.TextValue === channelInventoryConfiguration.InventoryOutOfStockAttributeValueText\r\n ) {\r\n // The matching recordId indicates that is the inventory attribute\r\n // if the text value are the same then is out of stock.\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Returns only in stock products.\r\n * @param products - The product.\r\n * @param channelInventoryConfiguration - The channel configuration.\r\n * @returns Filtered product search result.\r\n */\r\nfunction filterOutOfStockProducts(\r\n products: ProductSearchResult[],\r\n channelInventoryConfiguration: ChannelInventoryConfiguration\r\n): ProductSearchResult[] {\r\n if (!ArrayExtensions.hasElements(products)) {\r\n return [];\r\n }\r\n const filteredProducts: ProductSearchResult[] = [];\r\n\r\n for (const product of products) {\r\n if (!isOutOfStock(product, channelInventoryConfiguration)) {\r\n filteredProducts.push(product);\r\n }\r\n }\r\n return filteredProducts;\r\n}\r\n\r\n/**\r\n * Returns sorted products based on availability.\r\n * @param products - The product.\r\n * @param channelInventoryConfiguration - The channel configuration.\r\n * @returns Sorted product search result.\r\n */\r\nfunction sortsProductsBasedOnAvailability(\r\n products: ProductSearchResult[],\r\n channelInventoryConfiguration: ChannelInventoryConfiguration\r\n): ProductSearchResult[] {\r\n if (!ArrayExtensions.hasElements(products)) {\r\n return [];\r\n }\r\n const inStockProducts: ProductSearchResult[] = [];\r\n const outOfStockProducts: ProductSearchResult[] = [];\r\n\r\n for (const product of products) {\r\n if (isOutOfStock(product, channelInventoryConfiguration)) {\r\n outOfStockProducts.push(product);\r\n } else {\r\n inStockProducts.push(product);\r\n }\r\n }\r\n return inStockProducts.concat(outOfStockProducts);\r\n}\r\n\r\n/**\r\n * Returns list of products based on inventory information.\r\n * @param products - The products.\r\n * @param channelInventoryConfiguration - The channel configuration.\r\n * @param context - The context.\r\n * @returns List of product based on the inventory information.\r\n */\r\nexport function returnProductsBasedOnInventoryInformation(\r\n products: ProductSearchResult[],\r\n channelInventoryConfiguration: ChannelInventoryConfiguration,\r\n context: IActionContext\r\n): ProductSearchResult[] {\r\n if (!ArrayExtensions.hasElements(products) || ObjectExtensions.isNullOrUndefined(channelInventoryConfiguration)) {\r\n return [];\r\n }\r\n switch (context.requestContext.app.config.productListInventoryDisplay) {\r\n case ProductListInventoryFilteringOptions.HideOOS:\r\n return filterOutOfStockProducts(products, channelInventoryConfiguration);\r\n case ProductListInventoryFilteringOptions.SortOOS:\r\n return sortsProductsBasedOnAvailability(products, channelInventoryConfiguration);\r\n default:\r\n return products;\r\n }\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 * @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): Promise<IFullProductsSearchResultsWithCount> {\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 const channelInventoryConfiguration = await getInventoryConfigurationAsync({ callerContext: context });\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 // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- need check.\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 const productsBasedOnInventory = returnProductsBasedOnInventoryInformation(mappedProducts, channelInventoryConfiguration, context);\r\n return {\r\n products: productsBasedOnInventory,\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 };\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\nasync function action(input: GetFullProductsByCollectionInput, context: IActionContext): Promise<IFullProductsSearchResultsWithCount> {\r\n let promise: AsyncResult<ProductSearchResult[]>;\r\n let searchProductId;\r\n const searchCriteriaInput: ProductSearchCriteria = {};\r\n searchCriteriaInput.Context = {\r\n ChannelId: context.requestContext.apiSettings.channelId,\r\n CatalogId: context.requestContext.apiSettings.catalogId\r\n };\r\n searchCriteriaInput.Refinement = input.refiners;\r\n searchCriteriaInput.IncludeAttributes = input.includeAttributes;\r\n searchCriteriaInput.SkipVariantExpansion = true;\r\n const defaultNumber: number = 0;\r\n\r\n if (input.pageType === 'Category' || (context.requestContext.query && 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 && context.requestContext.query.q) {\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 (\r\n input.searchText &&\r\n context.requestContext.query &&\r\n context.requestContext.query.productId &&\r\n context.requestContext.query.recommendation\r\n ) {\r\n const searchObject = JSON.parse(input.searchText);\r\n searchProductId = Number(searchObject.ProductId);\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 searchCriteriaInput.RecommendationListId = searchObject.Recommendation;\r\n searchCriteriaInput.Ids = [searchProductId || 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 }\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 const productSearchResults = await promise;\r\n\r\n // Update ListPageState For SSR\r\n if (!MsDyn365.isBrowser) {\r\n context.update(new ListPageStateInput(), {\r\n totalProductCount: promise.metadata.count ?? defaultNumber,\r\n activeFilters: input.refiners\r\n });\r\n }\r\n\r\n return returnProducts(productSearchResults, context, promise.metadata.count);\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: <IAction<IFullProductsSearchResultsWithCount>>action,\r\n input: createInput\r\n});\r\n\r\nexport default actionDataAction;\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt 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<ITitle> = ({ text, className }) => (<span className={className}>\r\n {' '}\r\n {text}\r\n {' '}\r\n</span>);\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\n/* eslint-disable no-duplicate-imports */\r\n\r\nimport { CacheType, IActionInput, IAny, ICommerceApiSettings, ICreateActionContext, IGeneric } from '@msdyn365-commerce/core';\r\nimport { convertToString, IQueryResultSettings, ProductRefinerValue, SortColumn } from '@msdyn365-commerce/retail-proxy';\r\nimport { buildCacheKey, 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<IAny>, IGeneric<IAny>>): boolean {\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<IAny>, IGeneric<IAny>>): 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 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 ) {\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 }\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 = buildCacheKey(\r\n `${this.pageType}-${this.locale}-${this.category || this.searchText}-${this.refiners.map(\r\n refiner => `${refiner.RefinerRecordId + (refiner.LeftValueBoundString || '') + (refiner.RightValueBoundString || '')}-`\r\n )}-${convertToString(queryResultSettings)}`,\r\n this.apiSettings,\r\n 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) => 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\r\n if (args.requestContext.query && args.requestContext.query.sorting) {\r\n queryResultSettings.Sorting = { Columns: <SortColumn[]>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 undefined,\r\n includeAttributes,\r\n isUpdateRefinerPanel,\r\n args.requestContext.locale\r\n );\r\n } else if (pageType === 'Search' && args.requestContext.query && args.requestContext.query.q) {\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 );\r\n } else if (\r\n pageType === 'Search' &&\r\n args.requestContext.query &&\r\n args.requestContext.query.productId &&\r\n args.requestContext.query.recommendation\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 JSON.stringify({ ProductId: args.requestContext.query.productId, Recommendation: args.requestContext.query.recommendation }),\r\n includeAttributes,\r\n isUpdateRefinerPanel,\r\n args.requestContext.locale\r\n );\r\n }\r\n\r\n throw new Error('[getFullProductsForCollection]Unable to create input');\r\n};\r\n\r\n","import { Modal, ModalBody, ModalFooter, ModalHeader } from '@msdyn365-commerce-modules/utilities';\r\nimport * as React from 'react';\r\n\r\nexport interface IDobbiesModalProps {\r\n modalBodySlots?: React.ReactNode[];\r\n modalBodyElement?:JSX.Element;\r\n isOpen: boolean;\r\n className: string;\r\n modalTitle: JSX.Element;\r\n modalFooter: JSX.Element;\r\n onModalToggle?(): void;\r\n}\r\n\r\nconst DobbiesModal: React.FC<IDobbiesModalProps> = (props: IDobbiesModalProps) => {\r\nreturn (\r\n <Modal isOpen={props.isOpen} zIndex={1050} applicationNode={'renderPage'} autoFocus={true} toggle={props.onModalToggle} className={`dobbies-modal ${props.className}`}>\r\n {props.modalTitle && <ModalHeader> {props.modalTitle}</ModalHeader>}\r\n {props.modalBodySlots && <ModalBody className='dobbies-modal-body'>{props.modalBodySlots}</ModalBody>}\r\n {props.modalBodyElement && <ModalBody className='dobbies-modal-body'>{props.modalBodyElement}</ModalBody>}\r\n {props.modalFooter && <ModalFooter>{props.modalFooter}</ModalFooter>}\r\n </Modal>\r\n );\r\n};\r\n\r\nexport default DobbiesModal;","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { CacheType, createObservableDataAction, IAction, IActionContext, IActionInput, IAny, ICommerceApiSettings, ICreateActionContext, IGeneric } 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\ninterface SearchConfiguration {\r\n ProductSortColumns?: SortColumn[];\r\n}\r\n\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<MappedSearchConfiguration[]> {\r\n return getSearchConfigurationAsync({ callerContext: ctx }).then((searchConfiguration: SearchConfiguration) => {\r\n return (<MappedSearchConfiguration[]>(searchConfiguration.ProductSortColumns || []).map<MappedSearchConfiguration | undefined>((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<IGeneric<IAny>>): 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: <IAction<MappedSearchConfiguration[]>>getMappedSearchConfiguration,\r\n input: createInput\r\n});\r\n\r\nexport default getMappedSearchConfigurationDataAction;\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt 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<ILink> = ({ text, className, href, ariaLabel }) => (<a className={className} href={href} aria-label={ariaLabel}>\r\n {' '}\r\n {text}\r\n {' '}\r\n</a>);\r\n","/*--------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * See License.txt in the project root for license information.\r\n *--------------------------------------------------------------*/\r\n\r\n/* eslint-disable no-duplicate-imports */\r\nimport { getPayloadObject, getTelemetryAttributes, IPayLoad, ITelemetryContent } from '@msdyn365-commerce-modules/utilities';\r\nimport { IProductRefinerHierarchy } from '@msdyn365-commerce/commerce-entities';\r\nimport { RatingComponent } from '@msdyn365-commerce/components';\r\nimport { ICoreContext } from '@msdyn365-commerce/core';\r\nimport { /* ProductRefinerSource, */ ProductRefinerValue/* , RefinerType */ } from '@msdyn365-commerce/retail-proxy';\r\nimport * as React from 'react';\r\nimport { IRefineItemToggleNotification } from './refine-item-toggle-notification';\r\nimport { IRefineItemCommonProps } from './refine-item.props.common';\r\nimport { ProductRefinerSource, ProductRefinerTypeValue } from './utilities';\r\n\r\n/**\r\n * RefineItem properties\r\n */\r\nexport interface IRefineItemProps {\r\n\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 /** The telemetry content */\r\n telemetryContent?: ITelemetryContent;\r\n onToggle(notfication: Readonly<IRefineItemToggleNotification>): 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<IRefineItemProps, IRefineItemState> {\r\n private anchorType: React.RefObject<HTMLAnchorElement>;\r\n private payLoad: IPayLoad;\r\n\r\n 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 // tslint:disable-next-line:max-func-body-length\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 index,\r\n children,\r\n onToggle,\r\n context,\r\n telemetryContent,\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(`[refine-item] RefineItem without LeftValueBoundString: ${JSON.stringify(productRefinerValue)}`);\r\n }\r\n /* const isSingleSelect = parentProductRefinerHierarchy.RefinerTypeValue === RefinerType.SingleSelect; */\r\n const isSingleSelect = parentProductRefinerHierarchy.RefinerTypeValue === ProductRefinerTypeValue.Single;\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 if (productRefinerValue.LeftValueBoundString) {\r\n this.payLoad.contentAction.etext = productRefinerValue.LeftValueBoundLocalizedString;\r\n const attribute = getTelemetryAttributes(telemetryContent!, this.payLoad);\r\n const refinerRating = parseInt(productRefinerValue.LeftValueBoundString, 10);\r\n const ratingRefiner = this.props.selectedRefinerValues?.find(value => value.DataTypeValue === productRefinerValue.DataTypeValue);\r\n const selectedRating = parseInt(ratingRefiner?.LeftValueBoundString || '0', 10);\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 return (\r\n <li\r\n className='ms-refine-submenu-item'\r\n role='radio'\r\n aria-checked={isChecked}\r\n id={`${parentProductRefinerHierarchy.KeyName!}_${index}`}\r\n aria-label={`${parentProductRefinerHierarchy.KeyName!}_${index}`}\r\n >\r\n <a\r\n href={this._getRefinerUrl()}\r\n aria-label={`${parentProductRefinerHierarchy.KeyName!}_${productRefinerValue.LeftValueBoundLocalizedString}`}\r\n onClick={this._onClick}\r\n {...attribute}\r\n >\r\n <RatingComponent\r\n className={ratingComponentClass}\r\n avgRating={refinerRating}\r\n ratingCount={productRefinerValue.LeftValueBoundLocalizedString ?? productRefinerValue.LeftValueBoundString}\r\n hideCount={false}\r\n readOnly={true}\r\n ariaLabel=''\r\n context={context}\r\n id={this.props.moduleId}\r\n typeName={this.props.moduleTypeName}\r\n data={{}}\r\n />\r\n <span className='refine-submenu-item__rating'>{productRefinerValue.Count !== undefined && `(${productRefinerValue.Count})`}</span>\r\n </a>\r\n </li>\r\n );\r\n } else {\r\n return undefined;\r\n }\r\n } else {\r\n this.payLoad.contentAction.etext = productRefinerValue.LeftValueBoundLocalizedString || productRefinerValue.LeftValueBoundString;\r\n const attribute = getTelemetryAttributes(telemetryContent!, this.payLoad);\r\n return (\r\n <li className='ms-refine-submenu-item' id={`${parentProductRefinerHierarchy.KeyName!}_${index}`}>\r\n <a\r\n key={!!selectedRefinementCriterion ? 'true' : 'false'}\r\n ref={this.anchorType}\r\n href={this._getRefinerUrl()}\r\n tabIndex={0}\r\n onClick={this._onClick}\r\n className={itemTypeClassName}\r\n role={inputType}\r\n aria-checked={!!selectedRefinementCriterion}\r\n {...attribute}\r\n {...attrs}\r\n >\r\n <span className='ms-refine-submenu-item__label'>\r\n {productRefinerValue.LeftValueBoundLocalizedString || productRefinerValue.LeftValueBoundString}\r\n {productRefinerValue.Count !== undefined && ` (${productRefinerValue.Count})`}\r\n </span>\r\n </a>\r\n </li>\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: parentProductRefinerHierarchy,\r\n productRefinerValue: productRefinerValue,\r\n isSelecting: !selectedRefinementCriterion\r\n });\r\n }\r\n\r\n return '';\r\n }\r\n\r\n private _onClick = (e: React.MouseEvent<HTMLAnchorElement | HTMLInputElement>): 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: parentProductRefinerHierarchy,\r\n productRefinerValue: productRefinerValue,\r\n isSelecting: !selectedRefinementCriterion\r\n });\r\n\r\n setTimeout(\r\n () => {\r\n this.anchorType.current && this.anchorType.current.focus();\r\n },\r\n 0\r\n );\r\n }\r\n }\r\n}"],"sourceRoot":""}