) {\r\n super(props);\r\n\r\n // binds\r\n this._checkBalance = this._checkBalance.bind(this);\r\n this._areRefsValid = this._areRefsValid.bind(this);\r\n this._renderLookupResult = this._renderLookupResult.bind(this);\r\n this._renderFailure = this._renderFailure.bind(this);\r\n\r\n // refs\r\n this.cardRef = React.createRef();\r\n this.pinRef = React.createRef();\r\n\r\n // state init\r\n this.state = { card: '', pin: '', processing: false };\r\n }\r\n public render(): JSX.Element | null {\r\n const config = this.props.config;\r\n this._mergeWithDefaults();\r\n\r\n const CittaGiftCardBalanceCheckViewProps = {\r\n ...this.props,\r\n GiftCardBalanceCheckModuleProps: {\r\n moduleProps: this.props,\r\n className: classnames('citta-gift-card-balance-check', config.className)\r\n },\r\n GiftCardBalanceCheckCardNodeProps: {\r\n className: 'card-number-wrapper input-wrapper'\r\n },\r\n GiftCardBalanceCheckCardNode: this._renderCard(),\r\n GiftCardBalanceCheckPinNodeProps: {\r\n className: 'card-pin-wrapper input-wrapper'\r\n },\r\n GiftCardBalanceCheckPinNode: this._renderPin(),\r\n GiftCardBalanceCheckResultNode: this._renderLookupResult(),\r\n GiftCardBalanceCheckButtonNode: this._renderCheckBalance()\r\n };\r\n\r\n return this.props.renderView(CittaGiftCardBalanceCheckViewProps) as React.ReactElement;\r\n }\r\n\r\n private _mergeWithDefaults(): void {\r\n const propsIndex = CittaGiftCardBalanceCheck.propsIndex;\r\n const defaultConfig = CittaGiftCardBalanceCheck.defaultConfig;\r\n const config = this.props.config;\r\n for (let keyIndex = 0; keyIndex < propsIndex.length; keyIndex++) {\r\n const keyName = propsIndex[keyIndex];\r\n config[keyName] = config[keyName] || defaultConfig[keyIndex];\r\n }\r\n }\r\n\r\n private _renderCard(): React.ReactNode {\r\n const { cardNumberPlaceholderText } = this.props.config;\r\n return (\r\n \r\n );\r\n }\r\n\r\n private _renderPin(): React.ReactNode {\r\n const { pinNumberPlaceholderText } = this.props.config;\r\n return (\r\n \r\n );\r\n }\r\n\r\n private _renderCheckBalance(): React.ReactNode {\r\n const submitButtonProps: React.ButtonHTMLAttributes<{}> = {\r\n // disable if we're invalid or if we're processing a request\r\n disabled: !this._areRefsValid() || this.state.processing\r\n } as React.ButtonHTMLAttributes<{}>;\r\n return (\r\n \r\n );\r\n }\r\n\r\n private _renderLookupResult = (): React.ReactNode | null => {\r\n const { result } = this.state;\r\n if (!result) {\r\n return;\r\n }\r\n if (this.state.processing) {\r\n return {this.props.config.lookupWaitText}
;\r\n }\r\n const { success, balance, message } = result;\r\n const className = success ? 'success' : 'fail';\r\n return (\r\n \r\n {\r\n success ? this._renderSuccess(message, balance) : this._renderFailure(message)\r\n }\r\n
\r\n );\r\n }\r\n\r\n private _renderFailure(message?: string): React.ReactNode | null {\r\n return {message || this.props.config.lookupFailureMessage}
;\r\n }\r\n\r\n private _renderSuccess(message?: string, balance?: number): React.ReactNode | null {\r\n const formattedBalance: string = this.props.context.cultureFormatter.formatCurrency(balance || '' as React.ReactText);\r\n return (\r\n <>\r\n {message && {message}
}\r\n {this.props.resources.labelForSuccessfulGiftCardBalanceCheckResponse || 'Balance: '} {formattedBalance}
\r\n >\r\n );\r\n }\r\n\r\n private _areRefsValid(): boolean {\r\n const refKeys = ['cardRef', 'pinRef'];\r\n for (let keyIndex = 0; keyIndex < refKeys.length; keyIndex++) {\r\n const ref: React.RefObject | undefined = this[refKeys[keyIndex]];\r\n if (!ref || !ref.current || !ref.current.value) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n private _capture = (key: CittaGiftCardBalanceCheckStateKeys) => (event: React.ChangeEvent) => {\r\n const newState = { [key]: event.target.value };\r\n // @ts-ignore -- type is valid\r\n this.setState(newState);\r\n }\r\n\r\n private _checkBalance(): void {\r\n this.setState(previousState => {\r\n return {\r\n ...previousState,\r\n processing: true\r\n };\r\n // tslint:disable-next-line:align\r\n }, () => {\r\n // tslint:disable-next-line:no-floating-promises\r\n getGiftCardBalanceCheck(new GiftCardBalanceCheckInput(this.cardRef.current!.value, this.pinRef.current!.value), this.props.context.actionContext)\r\n .then((result) => {\r\n this.cardRef && this.cardRef.current && this.cardRef.current.value ? this.cardRef.current.value = '' : null;\r\n this.pinRef && this.pinRef.current && this.pinRef.current.value ? this.pinRef.current.value = '' : null;\r\n this.setState({\r\n result,\r\n processing: false\r\n });\r\n });\r\n });\r\n }\r\n}\r\n\r\nexport default CittaGiftCardBalanceCheck;\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\n\r\nimport { observer } from 'mobx-react';\r\nimport * as React from 'react';\r\n\r\nimport { IModuleProps, INodeProps } from '@msdyn365-commerce-modules/utilities';\r\nimport { ICittaProductpdfSpecificationData } from './citta-productpdf-specification.data';\r\nimport { ICittaProductpdfSpecificationProps } from './citta-productpdf-specification.props.autogenerated';\r\n\r\nexport interface ICittaProductpdfSpecificationViewProps extends ICittaProductpdfSpecificationProps {\r\n PdfSpecificationContainer: IModuleProps;\r\n PdfSpecificationContentContainer: INodeProps;\r\n PdfSpecificationContent: INodeProps;\r\n PdfSpecificationContentShow: boolean;\r\n ProductSku: string | undefined;\r\n}\r\n\r\n/**\r\n *\r\n * CittaProductpdfSpecification component\r\n * @extends {React.Component>}\r\n */\r\n\r\n@observer\r\nclass CittaProductpdfSpecification extends React.Component> {\r\n public render(): JSX.Element | null {\r\n const { config } = this.props;\r\n\r\n const content: ICittaProductpdfSpecificationData = this.props.data;\r\n\r\n const pdfSpecificationContent = this._getProductSpecificationContent(content, config.pdfSpecificationTitle ? config.pdfSpecificationTitle : '');\r\n const productSku = content && content.product && content.product.result && content.product.result.ItemId;\r\n const CittaProductpdfSpecificationViewProps = {\r\n ...this.props,\r\n PdfSpecificationContainer: {\r\n moduleProps: this.props,\r\n className: 'pdf-specification'\r\n },\r\n PdfSpecificationContentContainer: {\r\n className: 'pdf-specification-content',\r\n 'aria-label': config.pdfSpecificationTitle\r\n },\r\n PdfSpecificationContent: {\r\n tag: 'a',\r\n href: pdfSpecificationContent,\r\n 'aria-label': `Click here to read ${config.pdfSpecificationTitle}`,\r\n target: '_blank',\r\n rel: \"noopener\"\r\n },\r\n PdfSpecificationContentShow : pdfSpecificationContent ? true : false,\r\n ProductSku: productSku\r\n };\r\n\r\n return this.props.renderView(CittaProductpdfSpecificationViewProps) as React.ReactElement;\r\n }\r\n\r\n private _getProductSpecificationContent(content: ICittaProductpdfSpecificationData, specificationTitle: string): string {\r\n const productSpec = content.productSpecificationData.result;\r\n let contentText = '';\r\n if (productSpec) {\r\n productSpec.some(spec => {\r\n if (spec.TextValue && spec.Name === specificationTitle) {\r\n contentText = spec.TextValue;\r\n return true;\r\n }\r\n return false;\r\n });\r\n }\r\n return contentText;\r\n }\r\n}\r\n\r\nexport default CittaProductpdfSpecification;\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\nimport { Module, Node } from '@msdyn365-commerce-modules/utilities';\r\nimport * as React from 'react';\r\nimport { ICittaGiftCardBalanceCheckViewProps } from './citta-gift-card-balance-check';\r\nexport default (props: ICittaGiftCardBalanceCheckViewProps) => {\r\n const { GiftCardBalanceCheckModuleProps,\r\n GiftCardBalanceCheckCardNodeProps,\r\n GiftCardBalanceCheckCardNode,\r\n GiftCardBalanceCheckPinNodeProps,\r\n GiftCardBalanceCheckPinNode,\r\n GiftCardBalanceCheckResultNode,\r\n GiftCardBalanceCheckButtonNode } = props;\r\n return (\r\n \r\n \r\n {GiftCardBalanceCheckCardNode}\r\n \r\n \r\n {GiftCardBalanceCheckPinNode}\r\n \r\n {GiftCardBalanceCheckResultNode}\r\n {GiftCardBalanceCheckButtonNode}\r\n \r\n );\r\n};\r\n","/*!\n * Copyright (c) Microsoft Corporation.\n * All rights reserved. See LICENSE in the project root for license information.\n */\n\nimport { Module, Node } from '@msdyn365-commerce-modules/utilities';\nimport * as React from 'react';\n\nimport { ITileListItemViewProps } from './tile-list-item';\n\n/**\n *\n * ITileListItemViewProps component.\n * @param props - Component props.\n * @returns TileListView.\n */\nconst renderTileListItemContent = (props: ITileListItemViewProps): JSX.Element => {\n const {\n heading,\n paragraph,\n backgroundImage,\n links,\n thumbnailImage,\n tileListContainer,\n tileListImageContainer,\n tileListThumbnailImageContainer,\n tileListHeadingContainer\n } = props;\n\n return (\n \n {backgroundImage}\n \n {heading}\n {paragraph}\n {links}\n \n {thumbnailImage}\n \n );\n};\n\n/**\n *\n * TileListItemViewProps component.\n * @param props - Component props.\n * @returns TileListView.\n */\nexport const TileListItemViewComponent: React.FC = props => {\n const { tileListItem } = props;\n return {renderTileListItemContent(props)};\n};\n\nexport default TileListItemViewComponent;\n","/*!\n * Copyright (c) Microsoft Corporation.\n * All rights reserved. See LICENSE in the project root for license information.\n */\n\nimport * as Msdyn365 from '@msdyn365-commerce/core';\nimport { ArrayExtensions } from '@msdyn365-commerce-modules/retail-actions';\nimport { getPayloadObject, getTelemetryAttributes, ITelemetryContent, onTelemetryClick } from '@msdyn365-commerce-modules/utilities';\nimport * as React from 'react';\n\nimport { ILinksData } from '../tile-list-item.props.autogenerated';\n\n/**\n * Tile List links.\n */\nexport interface ITileListLinks {\n links: ILinksData[];\n requestContext: Msdyn365.IRequestContext;\n telemetryContent: ITelemetryContent;\n onTextChange?(index: number): (event: Msdyn365.ContentEditableEvent) => void;\n}\n\n/**\n *\n * ITileListLinks component.\n * @extends {React.PureComponent}\n */\nexport class TileListLinks extends React.PureComponent {\n public render(): JSX.Element {\n const editableLinks = this._mapEditableLinks(this.props.links);\n return (\n \n {editableLinks && ArrayExtensions.hasElements(editableLinks) ? (\n \n ) : null}\n
\n );\n }\n\n /**\n * ITileListLinks component.\n * @param linkdata - Link data.\n * @returns Editable links.\n */\n private readonly _mapEditableLinks = (linkdata: ILinksData[]): Msdyn365.ILinksData[] | null => {\n if (!ArrayExtensions.hasElements(linkdata)) {\n return null;\n }\n const editableLinks: Msdyn365.ILinksData[] = [];\n for (const link of linkdata) {\n // Construct telemetry attribute to render\n const payLoad = getPayloadObject('click', this.props.telemetryContent, '', '');\n const linkText = link.linkText ? link.linkText : '';\n payLoad.contentAction.etext = linkText;\n const attributes = getTelemetryAttributes(this.props.telemetryContent, payLoad);\n const editableLink: Msdyn365.ILinksData = {\n ariaLabel: link.ariaLabel,\n className: 'ms-tile-list__link',\n linkText: link.linkText,\n linkUrl: link.linkUrl.destinationUrl,\n openInNewTab: link.openInNewTab,\n role: 'button',\n additionalProperties: attributes,\n onClick: onTelemetryClick(this.props.telemetryContent, payLoad, linkText)\n };\n editableLinks.push(editableLink);\n }\n\n return editableLinks;\n };\n}\nexport default TileListLinks;\n","/*!\n * Copyright (c) Microsoft Corporation.\n * All rights reserved. See LICENSE in the project root for license information.\n */\n\nimport * as Msdyn365 from '@msdyn365-commerce/core';\nimport { ArrayExtensions, StringExtensions } from '@msdyn365-commerce-modules/retail-actions';\nimport { getTelemetryObject, IModuleProps, INodeProps, ITelemetryContent, NodeTag } from '@msdyn365-commerce-modules/utilities';\nimport * as React from 'react';\n\nimport { TileListLinks } from './components';\nimport { IHeadingData, ITileListItemProps } from './tile-list-item.props.autogenerated';\n\n/**\n * Tile-list-item view props.\n */\nexport interface ITileListItemViewProps extends ITileListItemProps<{}> {\n heading?: React.ReactNode;\n paragraph?: React.ReactNode;\n links?: React.ReactNode;\n backgroundImage?: React.ReactNode;\n thumbnailImage?: React.ReactNode;\n tileListItem: IModuleProps;\n tileListContainer: INodeProps;\n tileListImageContainer: INodeProps;\n tileListThumbnailImageContainer: INodeProps;\n tileListHeadingContainer: INodeProps;\n}\n\n/**\n *\n * TileListItem component.\n * @extends {React.PureComponent>}\n */\nexport class TileListItem extends React.PureComponent> {\n private readonly _telemetryContent: ITelemetryContent = getTelemetryObject(\n this.props.context.request.telemetryPageName!,\n this.props.friendlyName,\n this.props.telemetry\n );\n\n public constructor(props: ITileListItemProps<{}>) {\n super(props);\n }\n\n public render(): JSX.Element {\n const { heading, paragraph, backgroundImage, thumbnailImage, redirectionUrl, links } = this.props.config;\n const tileListLinks = links && ArrayExtensions.hasElements(links) && (\n \n );\n const tileListLinkContainer = {\n tag: 'a' as NodeTag,\n className: 'ms-tile-list-container',\n role: 'link',\n href: redirectionUrl?.linkUrl.destinationUrl,\n 'aria-label': redirectionUrl?.ariaLabel\n };\n\n const tileListButtonContainer = {\n tag: 'button' as NodeTag,\n className: 'ms-tile-list-container'\n };\n const viewProps: ITileListItemViewProps = {\n ...this.props,\n heading: this._createHeading(heading),\n paragraph: this._createParagraph(paragraph),\n backgroundImage: this._renderBackgroundImage(backgroundImage),\n thumbnailImage: this._renderThumbnailImage(thumbnailImage),\n links: tileListLinks,\n tileListItem: {\n moduleProps: this.props,\n className: ''\n },\n tileListContainer: redirectionUrl ? tileListLinkContainer : tileListButtonContainer,\n tileListImageContainer: {\n className: 'ms-tile-list__image'\n },\n tileListThumbnailImageContainer: {\n className: 'ms-tile-list__thumbnail_image',\n 'aria-hidden': 'true'\n },\n tileListHeadingContainer: {\n className: 'ms-tile-list__heading'\n }\n };\n\n return this.props.renderView(viewProps) as React.ReactElement;\n }\n\n /**\n * Handles heading content change event.\n * @param event - Content editable event.\n */\n public handleHeadingChange = (event: Msdyn365.ContentEditableEvent): void => {\n this.props.config.heading!.text = event.target.value;\n };\n\n /**\n * Handles paragraph content change event.\n * @param event - Content editable event.\n */\n public handleParagraphChange = (event: Msdyn365.ContentEditableEvent): void => {\n this.props.config.paragraph = event.target.value;\n };\n\n /**\n * Handles paragraph content change event.\n * @param linkIndex - Index of link in linkarray.\n * @returns Void.\n */\n public handleLinkTextChange = (linkIndex: number) => (event: Msdyn365.ContentEditableEvent): void => {\n if (this.props.config.links?.[Number(linkIndex)]) {\n this.props.config.links[Number(linkIndex)].linkText = event.target.value;\n }\n };\n\n private _createParagraph(text?: Msdyn365.RichText): React.ReactNode | null {\n if (!text) {\n return null;\n }\n return (\n \n );\n }\n\n private _createHeading(heading?: IHeadingData): React.ReactNode | null {\n if (!heading) {\n return null;\n }\n if (StringExtensions.isNullOrWhitespace(heading.text)) {\n return null;\n }\n\n return (\n \n );\n }\n\n private _renderBackgroundImage(item?: Msdyn365.IImageData, isAriaHiddenAttribute?: boolean): React.ReactNode | null {\n // If image is null, we want to render the placeholder SVG - by passing image data with empty src\n\n const defaultImageSettings: Msdyn365.IImageSettings = {\n viewports: {\n xs: { q: 'w=328&h=412&m=6', w: 328, h: 412 },\n sm: { q: 'w=328&h=412&m=6', w: 328, h: 412 },\n md: { q: 'w=315&h=412&m=6', w: 315, h: 412 },\n lg: { q: 'w=315&h=412&m=6', w: 315, h: 412 },\n xl: { q: 'w=315&h=412&m=6', w: 315, h: 412 }\n },\n lazyload: true\n };\n const verifiedImageSettings = item?.imageSettings?.viewports ? item.imageSettings : defaultImageSettings;\n\n return (\n \n );\n }\n\n private _renderThumbnailImage(\n item?: Msdyn365.IImageData,\n itemImageSettings?: Msdyn365.IImageSettings,\n isAriaHiddenAttribute?: boolean\n ): React.ReactNode | null {\n if (!item) {\n return null;\n }\n if (StringExtensions.isNullOrWhitespace(item.src)) {\n return null;\n }\n\n return (\n \n );\n }\n}\n\nexport default TileListItem;\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\n/* eslint-disable no-duplicate-imports */\r\nimport { Module } from '@msdyn365-commerce-modules/utilities';\r\nimport * as React from 'react';\r\nimport { ICittaProductAttributeCompanionProductViewProps } from './citta-product-attribute-companion-product';\r\n\r\nconst ContentBlockView: React.FC = (props) => {\r\n const {\r\n contentBlockContainer,\r\n linkItem\r\n } = props;\r\n\r\n if (linkItem) {\r\n return (\r\n \r\n { /* @ts-ignore */ }\r\n {linkItem}\r\n \r\n );\r\n } else {\r\n return (null);\r\n }\r\n};\r\n\r\nexport default ContentBlockView;\r\n"],"sourceRoot":""}