{"version":3,"file":"static/js/218419922706ed8bcc8c.bundle.js","mappings":"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","sources":["webpack://bju-press/./src/modules/buybox-kit-customizer/buybox-kit-customizer.tsx?261f","webpack://bju-press/./src/utilities/class-name-helper.ts?dd10","webpack://bju-press/./src/utilities/data-attribute-parser.ts?7345","webpack://bju-press/./src/utilities/global-constants.ts?5882","webpack://bju-press/./lib/buybox-kit-customizer/module-registration.js?2474","webpack://bju-press/external var \"React\"?0d3b","webpack://bju-press/external var \"ReactDOM\"?853b"],"sourcesContent":["//==============================================================================\r\n// Buybox Kit Customizer\r\n//\r\n// Allows user to customize a kit by selecting product options and add-ons.\r\n//==============================================================================\r\nimport * as React from 'react';\r\nimport { observable } from 'mobx';\r\nimport { observer } from 'mobx-react';\r\nimport classnames from 'classnames';\r\n\r\nimport { clsHelper } from '../../utilities/class-name-helper';\r\nimport { attrNames } from '../../utilities/global-constants';\r\nimport { convertProductAttributes, AttributesWithMetadata } from '../../utilities/data-attribute-parser';\r\n\r\nimport { ProductSearchResult, ProductSearchCriteria, SimpleProduct } from '@msdyn365-commerce/retail-proxy';\r\nimport { searchByCriteriaAsync } from '@msdyn365-commerce/retail-proxy/dist/DataActions/ProductsDataActions.g';\r\nimport { RichTextComponent, getCatalogId } from '@msdyn365-commerce/core';\r\nimport { format } from '@msdyn365-commerce-modules/utilities';\r\n\r\nimport { IBuyboxKitCustomizerData } from './buybox-kit-customizer.data';\r\nimport { IBuyboxKitCustomizerProps } from './buybox-kit-customizer.props.autogenerated';\r\n\r\n//==============================================================================\r\n// INTERFACES\r\n//==============================================================================\r\n// Formatted output data into strings to be sent to cart line and sales order line\r\nexport interface OutputData {\r\n electives: string; // '003100b:190|004100b:179|005100b:190'\r\n substitutions: string; // 'Science:30000|Math:40000'\r\n contents: string; // 'Heritage Studies 4*|English 4 Online'\r\n showContentsText: string; // 'Show Contents'\r\n}\r\n\r\nexport interface CustomizerData {\r\n subject?: string;\r\n itemId?: string;\r\n productName?: string;\r\n productPrice?: string;\r\n defaultItemId?: string;\r\n}\r\n\r\nexport interface CustomizerMap {\r\n subject: string;\r\n items: SubjectMap[];\r\n productName?: string;\r\n itemId?: string;\r\n}\r\n\r\nexport interface SubjectMap {\r\n itemId: string;\r\n isDefault?: boolean;\r\n productName?: string;\r\n productPrice?: string;\r\n}\r\n\r\nexport interface ContentsMap {\r\n itemId: string;\r\n productName: string;\r\n items: SubjectMap[];\r\n}\r\n\r\n//==============================================================================\r\n// CLASS NAME UTILITY\r\n//==============================================================================\r\nconst BASE_CLASS = 'buybox-kit-customizer';\r\nconst cls = (fragment?: string) => clsHelper(BASE_CLASS, fragment);\r\n\r\n//==============================================================================\r\n// CLASS DEFINITION\r\n//==============================================================================\r\n/**\r\n * BuyboxKitCustomizer component\r\n * @extends {React.Component>}\r\n */\r\n//==============================================================================\r\n@observer\r\nclass BuyboxKitCustomizer extends React.Component> {\r\n //==========================================================================\r\n // VARIABLES\r\n //==========================================================================\r\n @observable private isOpen = false;\r\n private readonly kitOptions = {\r\n electives: attrNames.kitElectives,\r\n substitutions: attrNames.kitSubstitutions,\r\n contents: attrNames.kitContents\r\n };\r\n @observable private productLists: {[key: string]: (CustomizerMap | ContentsMap)[]};\r\n @observable private customizerData: {[key: string]: CustomizerData[]};\r\n\r\n //==========================================================================\r\n // PUBLIC METHODS\r\n //==========================================================================\r\n //------------------------------------------------------\r\n // Constructor\r\n //------------------------------------------------------\r\n constructor(props: IBuyboxKitCustomizerProps) {\r\n super(props);\r\n this.productLists = this._constructLists(this.kitOptions);\r\n this.customizerData = this._constructLists(this.kitOptions);\r\n }\r\n\r\n //------------------------------------------------------\r\n // Invoked immediately after component is mounted\r\n //------------------------------------------------------\r\n public async componentDidMount(): Promise {\r\n await this._getProductList(this.kitOptions.electives, this._parseCustomizerData);\r\n await this._getProductList(this.kitOptions.substitutions, this._parseCustomizerData);\r\n await this._getProductList(this.kitOptions.contents, this._parseContentsData);\r\n\r\n // Update line attributes with customizer data - necessary to show contents even if customizations were not made\r\n this._setLineAttributes();\r\n }\r\n\r\n //------------------------------------------------------\r\n // Render function\r\n //------------------------------------------------------\r\n public render(): JSX.Element | null {\r\n const { config, resources } = this.props;\r\n const {\r\n [this.kitOptions.electives]: electives,\r\n [this.kitOptions.substitutions]: substitutions\r\n } = this.productLists;\r\n\r\n // If product lists are empty, do not render module\r\n if (!electives?.length && !substitutions?.length) {\r\n return null;\r\n }\r\n\r\n return (\r\n
\r\n\r\n {/* Only return step label if set up in config */}\r\n {config.labelCustomizer &&\r\n
\r\n {this._useKitSelector() && (\r\n \r\n {resources.buyboxKitCustomizer_stepLabel} 3:\r\n \r\n )}\r\n \r\n {config.labelCustomizer}\r\n \r\n
\r\n }\r\n\r\n
this._resetCustomizer(event)}>\r\n\r\n {/* Customizer collapsible box */}\r\n
\r\n\r\n {/* Elective subjects */}\r\n {electives &&\r\n
\r\n {/* Elective options */}\r\n {this._renderSubjects(electives as CustomizerMap[], this.kitOptions.electives, true)}\r\n
\r\n }\r\n\r\n {/* Substitution subjects */}\r\n {substitutions &&\r\n
\r\n {/* Substitutions info header */}\r\n
\r\n
\r\n {format(resources.buyboxKitCustomizer_subsHeading, config.subsTotal)}\r\n
\r\n {config.subsText && }\r\n
\r\n \r\n {resources.buyboxKitCustomizer_subsLabelRemaining}:\r\n \r\n \r\n {this._calculateSubstitutions(this.customizerData[this.kitOptions.substitutions])}\r\n \r\n
\r\n
\r\n {/* Substitution options */}\r\n {this._renderSubjects(substitutions as CustomizerMap[], this.kitOptions.substitutions, false)}\r\n
\r\n }\r\n\r\n
\r\n\r\n {/* Customizer buttons */}\r\n
\r\n {/* Opens customizer box, needs to remain a link to not be tied to form's submit */}\r\n \r\n {resources.buyboxKitCustomizer_subsButtonCustomize}\r\n \r\n {/* Closes customizer box and resets all choices, needs to be a button to tie to form's default submit behavior */}\r\n \r\n {resources.buyboxKitCustomizer_subsButtonReset}\r\n \r\n
\r\n\r\n
\r\n\r\n
\r\n );\r\n }\r\n\r\n //==========================================================================\r\n // PRIVATE METHODS\r\n //==========================================================================\r\n //------------------------------------------------------\r\n // Render subject list\r\n //------------------------------------------------------\r\n private readonly _renderSubjects = (subjects: CustomizerMap[], option: string, optional: boolean): JSX.Element => {\r\n return (\r\n
\r\n {subjects.map((subject, index) => {\r\n return (\r\n
\r\n
\r\n {subject.subject}\r\n
\r\n
\r\n {this._renderSelect(subject, option, optional)}\r\n
\r\n
\r\n );\r\n })}\r\n
\r\n );\r\n };\r\n\r\n //------------------------------------------------------\r\n // Render subject select\r\n //------------------------------------------------------\r\n private readonly _renderSelect = (subject: CustomizerMap, option: string, optional: boolean): JSX.Element => {\r\n // Check if subject has been changed by finding corresponding object in customizer data\r\n const isChanged = !!this.customizerData[option].find(dataSubject => dataSubject.subject === subject.subject);\r\n // Disable select if substitutions available has reached 0 and if this select has not been changed\r\n const isDisabled = this._calculateSubstitutions(this.customizerData[option]) <= 0 ? !isChanged : false;\r\n return (\r\n this._onSelectChange(event, option, subject)}\r\n >\r\n {/* Only add an opt out option when subject is optional */}\r\n {optional &&\r\n \r\n }\r\n {subject.items.map((item, index) => {\r\n return (\r\n \r\n {this._renderOption(item, optional)}\r\n \r\n );\r\n })}\r\n \r\n );\r\n };\r\n\r\n //------------------------------------------------------\r\n // Render each subject selector option\r\n //------------------------------------------------------\r\n private readonly _renderOption = (item: SubjectMap, optional: boolean): JSX.Element => {\r\n return (\r\n \r\n {item.productName || item.itemId}\r\n {optional && !!item.productPrice &&\r\n ` (${this.props.resources.buyboxKitCustomizer_electivePricePrefix} ${this.props.context.cultureFormatter.formatCurrency(item.productPrice)})`\r\n }\r\n \r\n );\r\n };\r\n\r\n //------------------------------------------------------\r\n // Get product list with parsed properties\r\n //------------------------------------------------------\r\n private readonly _getProductList = async (attribute: string, parseFunction: Function): Promise => {\r\n const convertedAttributes = this._getConvertedAttributes();\r\n const kitAttribute = convertedAttributes && convertedAttributes[attribute] as string;\r\n const parsedAttributes = kitAttribute && parseFunction(kitAttribute);\r\n\r\n const subjectItemIds = parsedAttributes && parsedAttributes.map((subject: CustomizerMap | ContentsMap) => subject.itemId);\r\n const subjectList = subjectItemIds && await this._getProducts(subjectItemIds);\r\n\r\n const subjectPromises = parsedAttributes && subjectList && parsedAttributes.map(async (subject: CustomizerMap | ContentsMap) => {\r\n const productItemIds = subject.items.map(item => item.itemId);\r\n const productList = await this._getProducts(productItemIds);\r\n\r\n const productResult = productList.map(item => {\r\n const itemId = item.ItemId!;\r\n const productName = item.Name;\r\n const productPrice = item.Price;\r\n return {itemId, productName, productPrice};\r\n });\r\n\r\n let subjectProductName = subject.productName;\r\n\r\n if (!subjectProductName && subject.itemId) {\r\n const subjectProduct = subjectList.find((product: ProductSearchResult) => product.ItemId === subject.itemId);\r\n subjectProductName = subjectProduct?.Name;\r\n }\r\n\r\n return {...subject, productName: subjectProductName, items: productResult};\r\n });\r\n\r\n // Wait for all subject requests to complete\r\n const subjectResult: (CustomizerMap | ContentsMap)[] = subjectPromises && await Promise.all(subjectPromises);\r\n\r\n this.productLists[attribute] = subjectResult || [];\r\n };\r\n\r\n //------------------------------------------------------\r\n // Get products from item IDs\r\n //------------------------------------------------------\r\n private readonly _getProducts = async (itemIds: string[]): Promise => {\r\n const { context } = this.props;\r\n\r\n const itemList = itemIds?.map(itemId => ({ ItemId: itemId }));\r\n\r\n // Build a ProductSearchCriteria object\r\n const criteria: ProductSearchCriteria = {\r\n ItemIds: itemList,\r\n Context: {\r\n ChannelId: context.request.apiSettings.channelId,\r\n CatalogId: getCatalogId(this.props.context.request)\r\n }\r\n };\r\n\r\n try {\r\n // Fetch search results\r\n const searchResults = await searchByCriteriaAsync({ callerContext: context.actionContext }, criteria);\r\n return searchResults;\r\n } catch (error) {\r\n if (context.telemetry) {\r\n context.telemetry.exception(error as Error);\r\n context.telemetry.debug('Unable to find products');\r\n }\r\n }\r\n\r\n return [];\r\n };\r\n\r\n //------------------------------------------------------\r\n // Parse kit customizer data into a friendlier format\r\n //\r\n // Ex input data: 'Heritage Studies:003100b,004100b*,\r\n // 005100b|English:003200b,004200b*,\r\n // 005200b'\r\n //------------------------------------------------------\r\n private readonly _parseCustomizerData = (customizerData: string): CustomizerMap[] => {\r\n return customizerData.split('|').map(property => {\r\n const splitData = property.split(':');\r\n return {\r\n subject: splitData[0],\r\n items: this._parseSubjectData(splitData[splitData.length - 1]) || [],\r\n itemId: this._findSubjectDefault(splitData[splitData.length - 1])\r\n };\r\n });\r\n };\r\n\r\n //------------------------------------------------------\r\n // Parse kit subject data into a friendlier format and\r\n // identify the default item\r\n //\r\n // Ex input data: '003100b,004100b*,005100b'\r\n //------------------------------------------------------\r\n private readonly _parseSubjectData = (subjectData: string): SubjectMap[] => {\r\n return subjectData.split(',').map(property => {\r\n // Item is default choice if includes *\r\n const isDefault = property.includes('*');\r\n\r\n // Remove * on default items when storing item ID\r\n let itemId = property;\r\n if (isDefault) {\r\n itemId = itemId.replace('*', '');\r\n }\r\n\r\n return {\r\n itemId,\r\n isDefault\r\n };\r\n });\r\n };\r\n\r\n //------------------------------------------------------\r\n // Find kit subject default item ID\r\n //\r\n // Ex input data: '003100b,004100b*,005100b'\r\n //------------------------------------------------------\r\n private readonly _findSubjectDefault = (subjectData: string): string | undefined => {\r\n const splitData = subjectData.split(',');\r\n const defaultItem = splitData.find(item => item.includes('*'))?.replace('*', '');\r\n return defaultItem;\r\n };\r\n\r\n //------------------------------------------------------\r\n // Parse kit contents data into a friendlier format\r\n //\r\n // Ex input data: 'American Republic DVD with Books\r\n // (4th ed.)|450635:515841,298380,\r\n // 298364,434506,433656,418327|English 8\r\n // DVD with Books|523092:523093,…'\r\n //------------------------------------------------------\r\n private readonly _parseContentsData = (contentsData: string): ContentsMap[] => {\r\n const splitData = contentsData.split('|');\r\n const parsedData = [];\r\n\r\n for (let i = 0; i < splitData.length; i+=2) {\r\n const separatedItemData = splitData[i+1].split(':');\r\n\r\n parsedData.push({\r\n productName: splitData[i],\r\n itemId: separatedItemData[0],\r\n items: this._parseItemsData(separatedItemData[separatedItemData.length - 1]) || []\r\n });\r\n }\r\n\r\n return parsedData;\r\n };\r\n\r\n //------------------------------------------------------\r\n // Parse kit items data into a friendlier format\r\n //\r\n // Ex input data: '515841,298380,298364'\r\n //------------------------------------------------------\r\n private readonly _parseItemsData = (itemsData: string): SubjectMap[] => {\r\n return itemsData.split(',').map(property => {\r\n return {\r\n itemId: property\r\n };\r\n });\r\n };\r\n\r\n //------------------------------------------------------\r\n // Convert customizer data to formatted output before\r\n // being sent to the cart\r\n //\r\n // Ex output data: {\r\n // electives: '003100b:190|004100b:179|005100b:190',\r\n // substitutions: 'Science:30000|Math:40000',\r\n // contents: 'Heritage Studies 4*|English 4 Online'\r\n // }\r\n //------------------------------------------------------\r\n private readonly _convertCustomizerData = (customizerData: {[key: string]: CustomizerData[]}): OutputData => {\r\n const electivesArray = customizerData[this.kitOptions.electives].map(elective => `${elective.itemId}:${elective.productPrice}`);\r\n const electives = electivesArray.join('|');\r\n const substitutionsArray = customizerData[this.kitOptions.substitutions].map(substitution => `${substitution.subject}:${substitution.itemId}`);\r\n const substitutions = substitutionsArray.join('|');\r\n const contents = this._getContentsData(customizerData);\r\n const showContentsText = this.props.resources.buyboxKitCustomizer_showContentsButton;\r\n return { electives, substitutions, contents, showContentsText };\r\n };\r\n\r\n //------------------------------------------------------\r\n // Gets kit content data, replaces substitutions, adds\r\n // electives, and finds each item's product name\r\n //------------------------------------------------------\r\n private readonly _getContentsData = (customizerData: {[key: string]: CustomizerData[]}): string => {\r\n const electives = customizerData[this.kitOptions.electives];\r\n const substitutions = customizerData[this.kitOptions.substitutions];\r\n const contents = this.productLists[this.kitOptions.contents] as ContentsMap[];\r\n\r\n // List out all kit content items\r\n const itemList = contents.map(item => {\r\n return {\r\n itemId: item.itemId,\r\n productName: item.productName\r\n };\r\n });\r\n\r\n // Find items in list that have substitutions\r\n const modifiedList = itemList.map(item => {\r\n const substitution = substitutions.find(subItem => subItem.defaultItemId === item.itemId);\r\n if (substitution) {\r\n return `${substitution.productName || substitution.itemId}*`;\r\n }\r\n return item.productName || item.itemId;\r\n });\r\n\r\n // Add electives to list\r\n electives.forEach(electiveItem => {\r\n const electiveString = electiveItem.productName || electiveItem.itemId;\r\n electiveString && modifiedList.unshift(`${electiveString}*`);\r\n });\r\n\r\n const finalList = modifiedList.join('|'); // Need to be stringified to be sent as line attributes\r\n\r\n return finalList;\r\n };\r\n\r\n //------------------------------------------------------\r\n // Get converted product attributes\r\n //------------------------------------------------------\r\n private readonly _getConvertedAttributes = (): AttributesWithMetadata | undefined => {\r\n const { data } = this.props;\r\n const productAttributes = data.productSpecificationData?.result;\r\n return productAttributes && convertProductAttributes(productAttributes);\r\n };\r\n\r\n //------------------------------------------------------\r\n // Construct each option list initializer based on array\r\n // of options\r\n //------------------------------------------------------\r\n private readonly _constructLists = (options: {[key: string]: string}): {[key: string]: []} => {\r\n const lists = {};\r\n Object.values(options).forEach(option => lists[option] = []);\r\n return lists;\r\n };\r\n\r\n //------------------------------------------------------\r\n // On select change\r\n //------------------------------------------------------\r\n private readonly _onSelectChange = (event: React.ChangeEvent, option: string, subject: CustomizerMap): void => {\r\n const currentItem = subject.items.find(item => item.itemId === event.currentTarget.value);\r\n // Check if the subject already exists in customizer data array\r\n const existingSubjectIndex = this.customizerData[option].findIndex(\r\n subjectItem => subjectItem.subject === event.currentTarget.name\r\n );\r\n // If the user selects the default option, remove the subject from customizerData\r\n if (event.currentTarget.value === subject.itemId) {\r\n if (existingSubjectIndex !== -1) {\r\n this.customizerData[option].splice(existingSubjectIndex, 1);\r\n }\r\n } else {\r\n // Update or add the subject in customizerData with the new selection\r\n if (existingSubjectIndex !== -1) {\r\n this.customizerData[option][existingSubjectIndex] = {\r\n subject: event.currentTarget.name,\r\n itemId: event.currentTarget.value,\r\n productName: currentItem?.productName,\r\n productPrice: currentItem?.productPrice,\r\n defaultItemId: subject.itemId\r\n };\r\n } else {\r\n this.customizerData[option].push({\r\n subject: event.currentTarget.name,\r\n itemId: event.currentTarget.value,\r\n productName: currentItem?.productName,\r\n productPrice: currentItem?.productPrice,\r\n defaultItemId: subject.itemId\r\n });\r\n }\r\n }\r\n // Update line attributes with customizer data\r\n this._setLineAttributes();\r\n };\r\n\r\n //------------------------------------------------------\r\n // Calculate remaining substitutions available\r\n //------------------------------------------------------\r\n private readonly _calculateSubstitutions = (substitutions?: CustomizerData[]): number => {\r\n const subsTotal = this.props.config.subsTotal;\r\n return substitutions ? (subsTotal - substitutions.length) : subsTotal;\r\n };\r\n\r\n //------------------------------------------------------\r\n // Reset customizer choices\r\n //------------------------------------------------------\r\n private readonly _resetCustomizer = (event: React.FormEvent): void => {\r\n event.preventDefault();\r\n\r\n // Reset form to revert select values to default\r\n event.currentTarget.reset();\r\n\r\n // Reconstruct empty customizer list to replace customizer data\r\n this.customizerData = this._constructLists(this.kitOptions);\r\n\r\n // Update line attributes with customizer data\r\n this._setLineAttributes();\r\n };\r\n\r\n //------------------------------------------------------\r\n // Toggle substitutions container\r\n //------------------------------------------------------\r\n private readonly _toggleSubstitutions = (): void => {\r\n this.isOpen = !this.isOpen;\r\n };\r\n\r\n //------------------------------------------------------\r\n // Set line attributes with output data\r\n //------------------------------------------------------\r\n private readonly _setLineAttributes = async (): Promise => {\r\n const product: SimpleProduct = await this.props.data.product;\r\n const lineAttributes = product.ExtensionProperties?.find(attribute => attribute.Key === attrNames.lineAttributes);\r\n const outputData = this._convertCustomizerData(this.customizerData);\r\n const hasKitData = outputData?.contents || outputData?.electives || outputData?.substitutions;\r\n\r\n // If product has no kit data, do not set any line attributes\r\n if (!hasKitData) {\r\n return;\r\n }\r\n\r\n if (lineAttributes?.Value) {\r\n lineAttributes.Value[attrNames.kitConfigurator] = outputData;\r\n } else {\r\n // Forcing extra layer into extension properties for selected adding to cart line attributes\r\n product.ExtensionProperties?.push({\r\n Key: attrNames.lineAttributes,\r\n Value: {\r\n [attrNames.kitConfigurator]: outputData\r\n }\r\n });\r\n }\r\n };\r\n\r\n //------------------------------------------------------\r\n // Determines whether kit selector will need to be used\r\n // by checking if kit formats attribute is populated\r\n //------------------------------------------------------\r\n private readonly _useKitSelector = (): boolean => {\r\n const convertedAttributes = this._getConvertedAttributes();\r\n const kitFormats = convertedAttributes && convertedAttributes[attrNames.kitFormats] as string;\r\n return kitFormats ? true : false;\r\n };\r\n}\r\n\r\nexport default BuyboxKitCustomizer;\r\n","//==============================================================================\r\n// Class Name Helper\r\n//\r\n// Tool to standardize CSS class naming in module components and elements\r\n//==============================================================================\r\n\r\nexport function clsHelper(baseClass: string, fragment?: string, separator: string = '__'): string | undefined {\r\n return fragment ? `${baseClass}${separator}${fragment}` : undefined;\r\n}\r\n","//==============================================================================\r\n// D365 OData Attribute Parser\r\n//\r\n// In creating this, it became clear that \"attributes\" is a general term.\r\n//\r\n// Product attributes are a first-class entity. They have their own dedicated\r\n// fields and schema.\r\n//\r\n// The more generic term \"attributes\" is used as a generic extension system.\r\n// Almost every entity (including Product Attributes) has an ExtensionProperties\r\n// field for jamming extra information into. In some cases, D365 handles these\r\n// natively, such as sales order line and header attributes, or customer\r\n// attributes. Attributes using ExtensionProperties use the\r\n// CommerceProperty and CommercePropertyValue types.\r\n//\r\n// A major note about ExtensionProperty-based attributes: they have fields\r\n// for many different data types, but there's no indicator as to which\r\n// of the fields is actually used. The consumer of the data is expected to\r\n// know the data type ahead of time. In the case of D365-native attribute users\r\n// such as customers and sales orders, only the string type appears to work.\r\n//\r\n// This module includes parsers for generic ExtensionProperties-based attributes\r\n// and Product Attributes. Though different Product Attribute retail server\r\n// calls use the same AttributeValue entity to transmit the data, they appear\r\n// to return different fields from that entity. Because of this, two different\r\n// parser calls are included here. They currently share the same implementation,\r\n// but by including different call signatures we have the ability to diverge\r\n// the implementations if the need arises.\r\n//\r\n// A note about Product Attributes: These contain both a friendly name,\r\n// displayed to users in back office, and an internal name. The internal name\r\n// can be the same as the friendly name, but by convention we've been pushing\r\n// for a PascalCase scheme. At present, the searchByCriteria call returns only\r\n// the unfriendly name, and the GetAttributeValues call returns only the\r\n// friendly name. We don't have a known method of correlating the two. That may\r\n// be an argument for keeping the friendly and unfriendly names identical.\r\n//==============================================================================\r\nimport {\r\n CommerceProperty, // Generic attributes stored in ExtensionProperties\r\n CommercePropertyValue, // Generic attributes stored in AttributeValue\r\n AttributeValue, AttributeDataType, // Product attributes or Product Search Result attributes\r\n CustomerAttribute, // Customer attributes\r\n IDictionary,\r\n} from '@msdyn365-commerce/retail-proxy';\r\n\r\n//==============================================================================\r\n// INTERFACES AND CONSTANTS\r\n//==============================================================================\r\nexport type CommerceValueTypes = string | number | boolean | Date;\r\n\r\n// This is me giving up on proper typing. If doing this in TypeScript is possible, I don't know how.\r\n// For the key \"meta\", the type should be a hash of strings.\r\n// For all other keys, the type is a CommerceValueType.\r\nexport type AttributesWithMetadata = {\r\n [key: string]: CommerceValueTypes | IDictionary\r\n};\r\n\r\n// Type to support both internal and friendly name for attributes\r\nexport type AttributesLocalized = {\r\n [key: string]: {\r\n friendlyName?: string,\r\n value?: CommerceValueTypes | IDictionary\r\n }\r\n};\r\n\r\n// Return type for getTypeInfo()\r\ntype TypeData = {\r\n source: keyof AttributeValue,\r\n type: string,\r\n\r\n customerSource?: keyof CommercePropertyValue,\r\n};\r\n\r\n//==============================================================================\r\n// FUNCTIONS\r\n//==============================================================================\r\n\r\n//----------------------------------------------------------\r\n// This version handles ExtensionProperties conversion.\r\n//\r\n// While these have a bunch of potential fields, the value\r\n// is always stored within StringValue.\r\n// There isn't a data type field, so if the content wasn't\r\n// in StringValue we wouldn't know where to find it.\r\n//----------------------------------------------------------\r\nexport function convertExtensionProperties(attributeList: CommerceProperty[]): IDictionary {\r\n const output = {};\r\n\r\n attributeList.forEach(entry => {\r\n if (entry.Key) {\r\n output[entry.Key] = entry.Value?.StringValue; // Ecommerce seems to always use strings.\r\n }\r\n });\r\n\r\n return output;\r\n}\r\n\r\n//----------------------------------------------------------\r\n// For these attributes, the Name is always the friendly\r\n// name.\r\n// KeyName and ExtensionProperties aren't defined.\r\n//\r\n// These results seem to be missing CurrencyValue,\r\n// FloatValue, DateTimeOffsetValue\r\n// I don't know if those data types aren't allowed here.\r\n//\r\n// Return value: Hash of key: property values with variable\r\n// types. There is also a \"meta\" key containing a hash of\r\n// all the attribute keys and their corresponding types.\r\n//\r\n// Example:\r\n// {\r\n// flavor: 'bland',\r\n// calories: 5300,\r\n// meta: {\r\n// flavor: 'string',\r\n// calories: 'number'\r\n// }\r\n// }\r\n//----------------------------------------------------------\r\nexport function convertProductAttributes(attributeList: AttributeValue[]): AttributesWithMetadata {\r\n const output = {\r\n meta: {}\r\n };\r\n\r\n attributeList.forEach(attribute => {\r\n // These should always be present, but TypeScript insists they can be undefined.\r\n if (attribute.Name && attribute.DataTypeValue) {\r\n const typeData = getTypeInfo(attribute.DataTypeValue);\r\n output[attribute.Name] = attribute[typeData.source]; // Ecommerce seems to require strings\r\n output.meta[attribute.Name] = typeData.type;\r\n }\r\n });\r\n\r\n return output;\r\n}\r\n\r\n//----------------------------------------------------------\r\n// For these attributes, the Name is the friendly\r\n// name while KeyName is the internal name.\r\n//\r\n// This makes use of combined attributes containing both\r\n// internal and friendly name to support localization.\r\n//\r\n// Return value: Hash of internal name keys containing an object with both the\r\n// friendly name and attribute value There is also a \"meta\" key containing a\r\n// hash of all the attribute keys and their corresponding types.\r\n//\r\n// Example:\r\n// {\r\n// flavor: {\r\n// friendlyName: Flavor,\r\n// value: 'bland'\r\n// },\r\n// calories: {\r\n// friendlyName: Calories,\r\n// value: 5300\r\n// },\r\n// meta: {\r\n// flavor: 'string',\r\n// calories: 'number'\r\n// }\r\n// }\r\n//----------------------------------------------------------\r\nexport function convertProductAttributesLocalized(attributeList: AttributeValue[]): AttributesLocalized {\r\n const output = {\r\n meta: {}\r\n };\r\n\r\n attributeList.forEach(attribute => {\r\n if (attribute.KeyName && attribute.DataTypeValue) {\r\n const typeData = getTypeInfo(attribute.DataTypeValue);\r\n output[attribute.KeyName] = {\r\n friendlyName: attribute.Name,\r\n value: attribute[typeData.source]\r\n };\r\n output.meta[attribute.KeyName] = typeData.type;\r\n }\r\n });\r\n\r\n return output;\r\n}\r\n\r\n//----------------------------------------------------------\r\n// For these attributes, the\r\n// Name/KeyName/ExtensionProperties is always the unfriendly\r\n// name.\r\n//\r\n// These results are only missing the Swatches field.\r\n//\r\n// Though the returned value is a bit different, at present\r\n// the implementation for convertProductAttributes works for\r\n// search results.\r\n// If they diverge in the future, extend this function.\r\n//----------------------------------------------------------\r\nexport function convertSearchAttributes(attributeList: AttributeValue[]): AttributesWithMetadata {\r\n return convertProductAttributes(attributeList);\r\n}\r\n\r\n//----------------------------------------------------------\r\n// For these attributes, the Name is always the friendly\r\n// name. Value is always Text, and DataTypeValue is not\r\n// present here.\r\n//----------------------------------------------------------\r\nexport function convertCartAttributes(attributeList: AttributeValue[]): AttributesWithMetadata {\r\n const output = {};\r\n\r\n attributeList.forEach(attribute => {\r\n if (attribute.Name) {\r\n output[attribute.Name] = attribute.TextValue;\r\n }\r\n });\r\n\r\n return output;\r\n}\r\n\r\n//----------------------------------------------------------\r\n//----------------------------------------------------------\r\nexport function convertCustomerAttributes(attributeList: CustomerAttribute[] | undefined): AttributesWithMetadata {\r\n const output = {\r\n meta: {}\r\n };\r\n\r\n attributeList?.forEach(attribute => {\r\n // These should always be present, but TypeScript insists they can be undefined.\r\n if (attribute.Name && attribute.DataTypeValue) {\r\n const typeData = getTypeInfo(attribute.DataTypeValue);\r\n output[attribute.Name] = attribute.AttributeValue && typeData.customerSource && attribute.AttributeValue[typeData.customerSource];\r\n output.meta[attribute.Name] = typeData.type;\r\n }\r\n });\r\n\r\n return output;\r\n}\r\n\r\n//----------------------------------------------------------\r\n// Finds the source field and type for an attribute\r\n//\r\n// This should probably be extended to better support\r\n// currency, which seems to be two fields glued together.\r\n//----------------------------------------------------------\r\nfunction getTypeInfo(type: AttributeDataType): TypeData {\r\n\r\n // Awkward, but this helps TypeScript enforce strict type checking\r\n type TypeMapType = {\r\n [key in AttributeDataType]: TypeData\r\n };\r\n\r\n const typeMap: TypeMapType = {\r\n [AttributeDataType.None]: {source: 'TextValue', type: 'string'}, // We need to choose something\r\n [AttributeDataType.Currency]: {source: 'CurrencyValue', type: 'number'}, // Should also include CurrencyCode, which is a string?\r\n [AttributeDataType.DateTime]: {source: 'DateTimeOffsetValue', type: 'Date'},\r\n [AttributeDataType.Decimal]: {source: 'FloatValue', type: 'number'},\r\n [AttributeDataType.Integer]: {source: 'IntegerValue', type: 'number', customerSource: 'IntegerValue'},\r\n [AttributeDataType.Text]: {source: 'TextValue', type: 'string', customerSource: 'StringValue'},\r\n [AttributeDataType.TrueFalse]: {source: 'BooleanValue', type: 'boolean', customerSource: 'BooleanValue'},\r\n [AttributeDataType.Video]: {source: 'TextValue', type: 'string'},\r\n [AttributeDataType.Image]: {source: 'TextValue', type: 'string'}\r\n };\r\n\r\n return typeMap[type];\r\n}\r\n","//==============================================================================\r\n// Global Constants\r\n//\r\n// Consolidated list of constants reused across different modules and extensions\r\n//==============================================================================\r\n\r\n//----------------------------------------------------------\r\n// Attribute names list\r\n//----------------------------------------------------------\r\nexport const attrNames = {\r\n productType: 'Item Type',\r\n lineAttributes: 'LineAttributes',\r\n blacklistedShippingAreas: 'Embargoed shipping locations',\r\n kitConfigurator: 'KitConfigurator',\r\n kitContents: 'eCommBurstoutKitContents',\r\n kitFormats: 'eCommBurstoutKitFormats',\r\n kitElectives: 'eCommBurstoutKitElectives',\r\n kitSubstitutions: 'eCommBurstoutKitSubstitutions',\r\n kitLineSubstitutions: 'eCommBurstoutKitLineDetails',\r\n kitLineParentAssociation: 'eCommBurstoutKitOrderLineParentAssociation',\r\n kitLineChildAssociation: 'eCommBurstoutKitOrderLineChildAssociation',\r\n instructors: 'eCommInstructors',\r\n consultantCartAttribute: 'eCommConsultantId',\r\n isInstallmentEligible: 'eCommItemIsPPEligible',\r\n cashForCollege: 'eCommCash4College',\r\n dropShip: 'eCommDropShip',\r\n scoringType: 'TestScoring',\r\n studentId: 'eCommPTEStudentId',\r\n schoolIdPP: 'eCommPPSchoolId',\r\n testCoordinator: 'PTETestCoordinator',\r\n testEnrollment: 'PTESchoolEnrollment',\r\n testType: 'Test Type',\r\n testFormat: 'Test Format',\r\n testDate: 'eCommPTETestDate',\r\n testDateId: 'eCommPTETestDateId',\r\n testAdmin: 'eCommPTEAdminCustAccount',\r\n testProctorEmail: 'PTEProctorEmail',\r\n testProctorName: 'PTEProctorName',\r\n testProctorPhone: 'PTEProctorPhone',\r\n testProctorTimeZone: 'PTEProctorTimeZone',\r\n userAgreement: 'eCommUserAgreement',\r\n umbrellaGroup: 'UmbrellaGroupID',\r\n gradeLvl: 'Grade level',\r\n isNotTest: 'Other',\r\n onlineTest: 'Online test',\r\n purchaseItemType: 'TestBklt',\r\n notBuyable: 'Not Buyable',\r\n billingCountry: 'eCommBillingCountryCode',\r\n billingZipCode: 'eCommBillingZipPostalCode',\r\n paymentScheduleName: 'PaymentScheduleName'\r\n};\r\n\r\n//----------------------------------------------------------\r\n// Global label resources\r\n//----------------------------------------------------------\r\nexport const labelResources = {\r\n sku: 'SKU'\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['buybox-kit-customizer'] = {\n c: () => require('partner/modules/buybox-kit-customizer/buybox-kit-customizer.tsx'),\n $type: 'contentModule',\n da: [{name:'product', path:'@msdyn365-commerce-modules/retail-actions/dist/lib/get-selected-variant', runOn: 0},{name:'productSpecificationData', path:'@msdyn365-commerce-modules/retail-actions/dist/lib/get-attributes-for-selected-variant', runOn: 0}],\n \n iNM: false,\n ns: '__local__',\n n: 'buybox-kit-customizer',\n p: '__local__',\n \n pdp: '',\n \n \n md: 'src/modules/buybox-kit-customizer'\n });\n \n\n {\n const sanitizedActionPath = '@msdyn365-commerce-modules/retail-actions/dist/lib/get-attributes-for-selected-variant';\n let dataAction = require('@msdyn365-commerce-modules/retail-actions/dist/lib/get-attributes-for-selected-variant');\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 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 };","module.exports = React;","module.exports = ReactDOM;"],"names":["BASE_CLASS","cls","fragment","clsHelper","BuyboxKitCustomizer","React","constructor","props","super","isOpen","kitOptions","electives","attrNames","kitElectives","substitutions","kitSubstitutions","contents","kitContents","_renderSubjects","subjects","option","optional","className","map","subject","index","key","this","_renderSelect","isChanged","customizerData","find","dataSubject","isDisabled","_calculateSubstitutions","name","defaultValue","disabled","onChange","event","_onSelectChange","value","resources","buyboxKitCustomizer_electiveOptOut","items","item","_renderOption","classnames","isDefault","itemId","productName","productPrice","buyboxKitCustomizer_electivePricePrefix","context","cultureFormatter","formatCurrency","_getProductList","async","attribute","parseFunction","convertedAttributes","_getConvertedAttributes","kitAttribute","parsedAttributes","subjectItemIds","subjectList","_getProducts","subjectPromises","productItemIds","productResult","ItemId","Name","Price","subjectProductName","subjectProduct","product","_objectSpread","subjectResult","Promise","all","productLists","criteria","ItemIds","itemIds","Context","ChannelId","request","apiSettings","channelId","CatalogId","getCatalogId","searchByCriteriaAsync","callerContext","actionContext","error","telemetry","exception","debug","_parseCustomizerData","split","property","splitData","_parseSubjectData","length","_findSubjectDefault","subjectData","includes","replace","_splitData$find","_parseContentsData","contentsData","parsedData","i","separatedItemData","push","_parseItemsData","itemsData","_convertCustomizerData","elective","join","substitution","_getContentsData","showContentsText","buyboxKitCustomizer_showContentsButton","modifiedList","subItem","defaultItemId","forEach","electiveItem","electiveString","unshift","_data$productSpecific","data","productAttributes","productSpecificationData","result","convertProductAttributes","_constructLists","options","lists","Object","values","currentItem","currentTarget","existingSubjectIndex","findIndex","subjectItem","splice","_setLineAttributes","subsTotal","config","_resetCustomizer","preventDefault","reset","_toggleSubstitutions","_product$ExtensionPro","lineAttributes","ExtensionProperties","Key","outputData","_product$ExtensionPro2","Value","kitConfigurator","_useKitSelector","kitFormats","render","labelCustomizer","buyboxKitCustomizer_stepLabel","onSubmit","format","buyboxKitCustomizer_subsHeading","subsText","RichTextComponent","text","buyboxKitCustomizer_subsLabelRemaining","role","onClick","buyboxKitCustomizer_subsButtonCustomize","buyboxKitCustomizer_subsButtonReset","__decorate","observable","observer","baseClass","separator","arguments","undefined","attributeList","output","meta","DataTypeValue","typeData","getTypeInfo","source","type","convertCartAttributes","TextValue","AttributeDataType","None","Currency","DateTime","Decimal","Integer","customerSource","Text","TrueFalse","Video","Image","productType","blacklistedShippingAreas","kitLineSubstitutions","kitLineParentAssociation","kitLineChildAssociation","instructors","consultantCartAttribute","isInstallmentEligible","cashForCollege","dropShip","scoringType","studentId","schoolIdPP","testCoordinator","testEnrollment","testType","testFormat","testDate","testDateId","testAdmin","testProctorEmail","testProctorName","testProctorPhone","testProctorTimeZone","userAgreement","umbrellaGroup","gradeLvl","isNotTest","onlineTest","purchaseItemType","notBuyable","billingCountry","billingZipCode","paymentScheduleName","labelResources","sku","binding","modules","dataActions","registerSanitizedActionPath","sanitizedActionPath","dataAction","default","Error","prototype","RegistrationId","id","c","require","$type","da","path","runOn","iNM","ns","n","p","pdp","md","window","__bindings__","module","exports","ReactDOM"],"sourceRoot":""}