, ICittaAccountSubscriptionState> {\r\n constructor(props: ICittaAccountSubscriptionViewProps) {\r\n super(props);\r\n this._handleSubscribeClick = this._handleSubscribeClick.bind(this);\r\n this._handleUnsubscribeClick = this._handleUnsubscribeClick.bind(this);\r\n const email = this.props.data && this.props.data.accountInformation && this.props.data.accountInformation.result?.Email;\r\n const subscribed = this._getSubscriptionState();\r\n const hasDetails = email !== undefined && subscribed !== undefined;\r\n\r\n this.state = {\r\n alertMessage: '',\r\n alertClass: '',\r\n userEmail: email || '',\r\n isSubscribed: subscribed || false,\r\n hasAccountDetails: hasDetails,\r\n isProcessing: false\r\n };\r\n }\r\n\r\n public componentDidUpdate(prevProps: ICittaAccountSubscriptionViewProps): void {\r\n if (this.props.data !== prevProps.data) {\r\n const { result } = this.props.data.accountInformation;\r\n if (result) {\r\n const email: string = this.props.data.accountInformation.result?.Email || '';\r\n const subscribed: boolean = this._getSubscriptionState() || false;\r\n const hasDetails1 = email !== undefined && subscribed !== undefined;\r\n this.setState({ userEmail: email, isSubscribed: subscribed, hasAccountDetails: hasDetails1 });\r\n }\r\n }\r\n\r\n }\r\n\r\n public render(): JSX.Element | null {\r\n const { hasAccountDetails, isProcessing } = this.state;\r\n const { config } = this.props;\r\n const CittaAccountSubscriptionViewProps = {\r\n ...this.props,\r\n AccountSubscriptionWrapper: {\r\n moduleProps: this.props,\r\n className: classnames('citta-account-subscription', config.className)\r\n },\r\n AccountSubscriptionAttribute: {\r\n className: 'citta-account-has-account'\r\n },\r\n AccountSubscriptionProcessing: {\r\n className: 'citta-account-subscription-processing'\r\n },\r\n AccountSubscriptionUnSubscribe: {\r\n className: 'citta-account-subscription-unsubscription'\r\n },\r\n subscribeResponse: this._getSubscribeResponse(),\r\n hasAccountDetails: hasAccountDetails,\r\n isProcessing: isProcessing,\r\n processingMessage: this._renderProcessing(),\r\n subUnsubButtton: this._renderButtons(),\r\n subscribeAlert: this._renderSubscribeAlert(),\r\n subscribeNote: this._renderSubscribeNote()\r\n };\r\n return this.props.renderView(CittaAccountSubscriptionViewProps) as React.ReactElement;\r\n }\r\n private _getSubscriptionState(): boolean | undefined {\r\n const accountInfo = this.props.data.accountInformation.result;\r\n if (accountInfo) {\r\n const attributes = accountInfo.Attributes;\r\n if (attributes && attributes.length > 0) {\r\n let isSubscribed;\r\n attributes.forEach(attr => {\r\n if (attr.Name === this.props.resources.optInAttributeName) {\r\n isSubscribed = attr.AttributeValue?.BooleanValue;\r\n }\r\n });\r\n return isSubscribed;\r\n }\r\n }\r\n return;\r\n }\r\n private _getSubscribeResponse(): React.ReactNode {\r\n const { isSubscribed, hasAccountDetails } = this.state;\r\n const { resources } = this.props;\r\n const message = hasAccountDetails\r\n ? {resources.subscribtionText} {isSubscribed ? resources.subscribtionStatus : resources.noSubscribtionStatus}{resources.subscribtionMailText}
\r\n : {resources.missingInfoMessage}
;\r\n\r\n return (\r\n \r\n
{resources.emailHeadingText}
\r\n {message}\r\n \r\n );\r\n }\r\n\r\n private _renderProcessing(): React.ReactNode {\r\n const { resources } = this.props;\r\n return (\r\n \r\n
{resources.processingLabel}
\r\n
\r\n );\r\n }\r\n\r\n // Render subscribe/unsubscribe button\r\n private _renderButtons(): React.ReactNode {\r\n const { resources } = this.props;\r\n const { isSubscribed, isProcessing } = this.state;\r\n if (isSubscribed) {\r\n return (\r\n \r\n );\r\n } else {\r\n return (\r\n \r\n );\r\n }\r\n }\r\n\r\n // Set-subscription alert message\r\n private _renderSubscribeAlert(): React.ReactNode {\r\n const { alertMessage, alertClass } = this.state;\r\n const displayAlert: boolean = (alertMessage ? alertMessage !== '' : false);\r\n if (displayAlert) {\r\n return (\r\n \r\n );\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n private _renderSubscribeNote(): React.ReactNode {\r\n const { resources } = this.props;\r\n return (\r\n \r\n
{resources.pleaseNoteMessage}
\r\n
\r\n );\r\n }\r\n\r\n private _handleSubscribeClick = async () => {\r\n await this._handleButtonClick(true);\r\n }\r\n\r\n private _handleUnsubscribeClick = async () => {\r\n await this._handleButtonClick(false);\r\n }\r\n\r\n private _handleButtonClick = async (subscribe: boolean) => {\r\n const { userEmail } = this.state;\r\n this.setState({\r\n isProcessing: true\r\n });\r\n // Update subscription state for user\r\n const response = await this._setSubscriptionState(userEmail, subscribe);\r\n if (response.Result && response.Message) {\r\n const isSuccess = this._isSuccess(subscribe, response.Message);\r\n this.setState({\r\n alertMessage: `${response.Message}`,\r\n alertClass: isSuccess ? 'alert-green' : 'alert-yellow',\r\n isProcessing: false\r\n });\r\n } else {\r\n this.setState({\r\n alertMessage: 'Error processing request',\r\n alertClass: 'alert-yellow',\r\n isProcessing: false\r\n });\r\n }\r\n }\r\n\r\n private async _setSubscriptionState(email: string, subscribed: boolean): Promise {\r\n try {\r\n return await subscribeEmailAction(new SubscribeEmailDataActionInput(email, subscribed), this.props.context.actionContext);\r\n } catch (e) {\r\n throw this.props.telemetry.error(`Something went wrong ------${e}`);\r\n }\r\n }\r\n\r\n private _isSuccess(subscribe: boolean, message: string): boolean {\r\n if (subscribe) {\r\n return message === 'Subscribed successfully.';\r\n } else {\r\n return message === 'Unsubscribed successfully.';\r\n }\r\n }\r\n}\r\n\r\nexport default CittaAccountSubscription;\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 { IAccordionItemViewProps } from './accordion-item';\n\nconst AccordionItemView: React.FC = props => {\n const { drawer, accordionSlots, AccordionItemContainer, AccordionItemContent } = props;\n return (\n \n \n \n {accordionSlots &&\n accordionSlots.accordionItemContent &&\n accordionSlots.accordionItemContent.length &&\n _renderAccordionItemContent(accordionSlots.accordionItemContent)}\n \n \n \n );\n};\n\nconst _renderAccordionItemContent = (items: React.ReactNode[]): JSX.Element | null => {\n return (\n <>\n {items && items.length > 0\n ? items.map((item: React.ReactNode, index: number) => {\n return {item};\n })\n : null}\n >\n );\n};\nexport default AccordionItemView;\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 { ControlledDrawer, getTelemetryObject, IModuleProps, INodeProps, ITelemetryContent } from '@msdyn365-commerce-modules/utilities';\nimport { IDrawerState } from '@msdyn365-commerce-modules/utilities/dist/types/drawer/Drawer';\nimport classnames from 'classnames';\nimport { observer } from 'mobx-react';\nimport * as React from 'react';\n\nimport { createAccordionStateInput, interactionStyle } from '../..';\nimport { IAccordionItemData } from './accordion-item.data';\nimport { IAccordionItemProps } from './accordion-item.props.autogenerated';\n\nexport interface IAccordionItemViewProps {\n AccordionItemContainer: IModuleProps;\n drawer: INodeProps;\n accordionSlots: INodeProps;\n AccordionItemContent: INodeProps;\n className: string;\n}\n\nexport interface IAccordionItemExtentedProps extends IAccordionItemProps {\n interactionStyle?: interactionStyle;\n}\n\n/**\n *\n * AccordionItem component.\n * @extends {React.Component}\n */\n@observer\nclass AccordionItem extends React.Component {\n private readonly moduleClassName: string = 'ms-accordion-item';\n\n private readonly telemetryContent?: ITelemetryContent;\n\n constructor(props: IAccordionItemProps) {\n super(props);\n this._onToggle = this._onToggle.bind(this);\n this.telemetryContent = getTelemetryObject(\n this.props.context.request.telemetryPageName!,\n this.props.friendlyName,\n this.props.telemetry\n );\n }\n\n public shouldComponentUpdate(nextProps: IAccordionItemProps): boolean {\n if (this.props.data === nextProps.data) {\n return false;\n }\n return true;\n }\n\n public render(): JSX.Element {\n const { slots, renderView, config, data } = this.props;\n const accordionExpandedStateResult = data && data.accordionExpandedState && data.accordionExpandedState.result;\n const expanded =\n accordionExpandedStateResult && accordionExpandedStateResult.isAllExpanded === undefined\n ? data && config.isExpandedOnInitialLoad\n : accordionExpandedStateResult && accordionExpandedStateResult.isAllExpanded;\n const viewProps = {\n ...this.props,\n AccordionItemContainer: {\n moduleProps: this.props,\n className: classnames(this.moduleClassName, config.className)\n },\n AccordionItemContent: {\n className: 'ms-accordion-item-content'\n },\n drawer: {\n tag: ControlledDrawer,\n className: `${this.moduleClassName}__drawer`,\n toggleButtonText: (config.accordionItemTitle && config.accordionItemTitle) || '',\n collapseProps: { isOpen: expanded },\n onToggle: this._onToggle,\n onTextChange: this.handleHeadingChange,\n requestContext: this.props.context.request,\n telemetryContent: this.telemetryContent\n },\n accordionSlots: slots\n };\n return renderView(viewProps) as React.ReactElement;\n }\n\n public handleHeadingChange = (event: Msdyn365.ContentEditableEvent) => (this.props.config.accordionItemTitle = event.target.value);\n\n private _onToggle(state: IDrawerState): void {\n if (!state.isOpen && this.props.interactionStyle === interactionStyle.ExpandOneItemOnly) {\n const accordionState = { isAllExpanded: false };\n this.props.context.actionContext.update(createAccordionStateInput(accordionState), accordionState);\n }\n }\n}\nexport default AccordionItem;\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 { IAccordionViewProps } from './accordion';\n\nconst accordionView: React.FC = props => {\n const { heading, AccordionContainer, accordionItems } = props;\n if (!props.heading && !props.accordionButtons && !props.accordionItems) {\n props.context.telemetry.error('Accordion content is empty, module wont render');\n return null;\n }\n return (\n \n \n {heading}\n {props.accordionButtons && {props.accordionButtons}}\n \n {accordionItems}\n \n );\n};\n\nexport default accordionView;\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 React, { ReactNode } from 'react';\n\nimport { IInteractiveFeatureCollectionViewProps } from './interactive-feature-collection';\n\n/**\n * Feature Collection View.\n * @param props - Feature Collection view props.\n * @returns Feature Collection View.\n */\nexport const interactiveFeatureCollectionView: React.FC = props => {\n const {\n title,\n interactiveFeatureCollectionHeading,\n interactiveFeatureCollectionContainer,\n interactiveFeatureCollectionDesktopContainer,\n interactiveFeatureCollectionDesktopItems,\n interactiveFeatureCollectionMobileItems,\n interactiveFeatureCollectionMobileContainer,\n singleSlideCarouselComponentProps,\n singleSlideCarouselItemContainer\n } = props;\n return (\n \n {title}\n {interactiveFeatureCollectionDesktopItems}\n \n \n {interactiveFeatureCollectionMobileItems &&\n interactiveFeatureCollectionMobileItems.map((tileItem: ReactNode, index: number) => {\n const keyIndex = `interactive-feature-carousel-item__${index}`;\n return (\n \n {tileItem}\n \n );\n })}\n \n \n \n );\n};\n\nexport default interactiveFeatureCollectionView;\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 { Button } from '@msdyn365-commerce-modules/utilities';\r\nimport { IVideoPlayerViewProps } from '@msdyn365-commerce-modules/video-player/src/modules/video-player/video-player';\r\n// import { IPlayerResources } from '@msdyn365-commerce/components/dist/types/videoplayer/components/data/player-resources';\r\nimport { Image } from '@msdyn365-commerce/core';\r\nimport * as React from 'react';\r\nimport { IVideoPlayerProps } from '../definition-extensions/video-player.ext.props.autogenerated';\r\n\r\ninterface IVideoPlayerState {\r\n isMobile: boolean;\r\n }\r\n\r\n/**\r\n *\r\n * VideoPlayer component\r\n * @extends {React.PureComponent}\r\n */\r\nexport class VideoPlayerView extends React.PureComponent, IVideoPlayerState> {\r\n constructor(props: IVideoPlayerViewProps) {\r\n //@ts-ignore\r\n super(props);\r\n this.state = {isMobile: false};\r\n }\r\n\r\n public componentDidMount(): void {\r\n this._updateIsMobile();\r\n window.addEventListener('resize', this._updateIsMobile);\r\n }\r\n\r\n public componentWillUnmount(): void {\r\n window.removeEventListener('resize', this._updateIsMobile);\r\n }\r\n\r\n public render(): JSX.Element | null {\r\n return (\r\n \r\n
\r\n {this.state.isMobile ? this._renderMobile() : this._renderDesktop()}\r\n {this._renderVideoPlayerOverlay()}\r\n
\r\n
\r\n );\r\n }\r\n\r\n private _renderDesktop = (): React.ReactNode | null => {\r\n const playerResources: any = {\r\n playAriaLabel: this.props.config.playLabel ? this.props.config.playLabel : '',\r\n pauseAriaLabel: this.props.config.pauseLabel ? this.props.config.pauseLabel : '',\r\n muteAriaLabel: this.props.config.muteLabel ? this.props.config.muteLabel : '',\r\n unMuteAriaLabel: this.props.config.unMuteLabel ? this.props.config.unMuteLabel: '',\r\n fullScreenAriaLabel: this.props.config.fullScreenLabel ? this.props.config.fullScreenLabel : '',\r\n exitFullScreenAriaLabel: this.props.config.exitFullScreenLabel ? this.props.config.exitFullScreenLabel : '',\r\n playingAriaLabel: this.props.config.playingLabel ? this.props.config.playingLabel : '',\r\n pausedAriaLabel: this.props.config.pausedLabel ? this.props.config.pausedLabel : '',\r\n ...this.props.resources\r\n };\r\n if (this.props.player) {\r\n return React.cloneElement(this.props.player as React.ReactElement, {playerResources});\r\n }\r\n return null;\r\n };\r\n\r\n private _renderMobile = (): React.ReactNode | null => {\r\n const imageSettingsDefault = {\r\n disableLazyLoad: true,\r\n viewports: {\r\n xs: { q: `q=80&w=770&h=500&m=6`, w: 770, h: 500 }\r\n }\r\n };\r\n const image = this.props.config.mobileImage;\r\n\r\n if (image) {\r\n return (\r\n \r\n {image && }\r\n
\r\n );\r\n }\r\n return null;\r\n }\r\n\r\n private _renderVideoPlayerOverlay = (): React.ReactNode | null => {\r\n const { buttonText, buttonLink, headerText, horizontalPosition } = this.props.config;\r\n if (buttonText || headerText) {\r\n return (\r\n \r\n { headerText &&
{headerText}
}\r\n { buttonText && }\r\n \r\n );\r\n }\r\n return null;\r\n };\r\n\r\n private _updateIsMobile = () => {\r\n this.setState({\r\n isMobile: window.innerWidth < 768\r\n });\r\n }\r\n}\r\n\r\nexport default VideoPlayerView;","/*!\n * Copyright (c) Microsoft Corporation.\n * All rights reserved. See LICENSE in the project root for license information.\n */\n\nimport {\n getTelemetryObject,\n IComponentNodeProps,\n IModuleProps,\n INodeProps,\n ISingleSlideCarouselProps,\n ITelemetryContent,\n NodeTag,\n SingleSlideCarousel\n} from '@msdyn365-commerce-modules/utilities';\nimport classnames from 'classnames';\nimport * as Msdyn365 from '@msdyn365-commerce/core';\nimport * as React from 'react';\n\nimport { IInteractiveFeatureCollectionProps } from './interactive-feature-collection.props.autogenerated';\n\n/**\n * Interactive Feature Collection view props.\n */\nexport interface IInteractiveFeatureCollectionViewProps extends IInteractiveFeatureCollectionProps<{}> {\n title: React.ReactNode;\n interactiveFeatureCollectionHeading: INodeProps;\n interactiveFeatureCollectionContainer: IModuleProps;\n interactiveFeatureCollectionDesktopContainer: INodeProps;\n interactiveFeatureCollectionDesktopItems: React.ReactNode[];\n interactiveFeatureCollectionMobileContainer: INodeProps;\n interactiveFeatureCollectionMobileItems: React.ReactNode[];\n singleSlideCarouselComponentProps: INodeProps;\n singleSlideCarouselItemContainer: INodeProps;\n}\n\n/**\n *\n * InteractiveFeatureCollection component.\n * @extends {React.PureComponent>}\n */\nexport class InteractiveFeatureCollection 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 private static _getFeatureItem(item: React.ReactNode, index: number, itemsCounter: number): React.ReactNode {\n const keyIndex = `interactive-feature-mosaic-item__${index}`;\n return (\n \n {React.cloneElement(item as React.ReactElement, { indexItem: index, itemCounter: itemsCounter, isMosaic: true })}\n \n );\n }\n\n public constructor(props: IInteractiveFeatureCollectionProps) {\n super(props);\n }\n\n public render(): JSX.Element | null {\n const { resources } = this.props;\n const { title, className } = this.props.config;\n const interactiveItems = this.props.slots && this.props.slots.interactiveFeatureItems;\n const itemsFeatureCounter = interactiveItems && interactiveItems.length;\n const singleSlideCarouselComponentProps: IComponentNodeProps = {\n tag: SingleSlideCarousel,\n className: this.props.config.className ?? '',\n flipperPrevLabel: resources.flipperPrevious,\n flipperNextLabel: resources.flipperNext,\n parentId: this.props.id,\n telemetryContent: this._telemetryContent,\n vertical: false\n };\n const initItemsFeatureCounter = 0;\n const createHeading = title && (\n \n );\n const viewProps = {\n ...this.props,\n title: createHeading,\n interactiveFeatureCollectionHeading: {\n className: 'ms-interactive-feature-collection__heading'\n },\n interactiveFeatureCollectionContainer: {\n moduleProps: this.props,\n className: classnames('ms-interactive-feature-collection', className)\n },\n interactiveFeatureCollectionDesktopContainer: {\n tag: 'div' as NodeTag,\n className: 'ms-interactive-feature-collection-desktop'\n },\n interactiveFeatureCollectionMobileContainer: {\n tag: 'div' as NodeTag,\n className: 'ms-interactive-feature-collection-mobile'\n },\n singleSlideCarouselComponentProps,\n singleSlideCarouselItemContainer: {\n tag: 'li' as NodeTag,\n className: 'ms-interactive-feature-collection-carousel',\n role: 'listitem'\n },\n interactiveFeatureCollectionMobileItems: this.props.slots.interactiveFeatureItems,\n interactiveFeatureCollectionDesktopItems:\n itemsFeatureCounter > initItemsFeatureCounter &&\n interactiveItems.map((item: React.ReactNode, index: number) =>\n InteractiveFeatureCollection._getFeatureItem(item, index, itemsFeatureCounter)\n )\n };\n return this.props.renderView(viewProps) as React.ReactElement;\n }\n\n /**\n * To handle text change.\n * @param event - To handle text change event.\n * @name - HandleTextChange\n * @public\n * @returns - The Text value.\n */\n public handleTextChange = (event: Msdyn365.ContentEditableEvent) => (this.props.config.title!.text = event.target.value);\n}\n\nexport default InteractiveFeatureCollection;\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\nimport { Module, Node } from '@msdyn365-commerce-modules/utilities';\r\nimport * as React from 'react';\r\nimport { ICittaAccountSubscriptionViewProps } from './citta-account-subscription';\r\n\r\nconst CittaAccountSubscriptionView: React.FC = props => {\r\n const {\r\n AccountSubscriptionWrapper,\r\n AccountSubscriptionAttribute,\r\n AccountSubscriptionProcessing,\r\n AccountSubscriptionUnSubscribe,\r\n subscribeResponse,\r\n subUnsubButtton,\r\n isProcessing,\r\n hasAccountDetails,\r\n processingMessage,\r\n subscribeAlert,\r\n subscribeNote } = props;\r\n return (\r\n \r\n {subscribeResponse}\r\n {hasAccountDetails &&\r\n \r\n {isProcessing ?\r\n \r\n {processingMessage}\r\n :\r\n \r\n {subUnsubButtton}\r\n {subscribeAlert}\r\n {subscribeNote}\r\n }\r\n \r\n }\r\n \r\n );\r\n};\r\n\r\nexport default CittaAccountSubscriptionView;\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 { CacheType, createObservableDataAction, IAction, IActionContext, IActionInput } from '@msdyn365-commerce/core';\r\nimport { dXC_SubscribeEmailAsync } from '../generated/DataActionExtension.g';\r\nimport { IDXC_SubscribeNewsletterRealtimeResponse } from '../generated/DataServiceEntities.g';\r\n\r\n/**\r\n * SubmitSubscribeFormDataActionInput Input Action\r\n */\r\n\r\nexport class SubscribeEmailDataActionInput implements IActionInput {\r\n public emailAddress: string;\r\n public subscribe: boolean;\r\n\r\n // Construct the input needed to run the action\r\n constructor(emailAddress: string, subscribe: boolean) {\r\n this.emailAddress = emailAddress;\r\n this.subscribe = subscribe;\r\n }\r\n\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 = () => 'SubscribeEmail2020';\r\n public getCacheObjectType = () => 'SubscribeEmail';\r\n public dataCacheType = (): CacheType => 'request';\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 = (args: SubscribeEmailDataActionInput): IActionInput => {\r\n return args;\r\n};\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 subscribeEmailAction(\r\n input: SubscribeEmailDataActionInput,\r\n ctx: IActionContext\r\n): Promise {\r\n // Input only needs token\r\n let result: IDXC_SubscribeNewsletterRealtimeResponse = {};\r\n try {\r\n result = await dXC_SubscribeEmailAsync({ callerContext: ctx }, input.emailAddress, input.subscribe);\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n return Array.isArray(result) ? result[0] : result;\r\n}\r\n\r\nexport const ISubscribeEmailDataActionAction = createObservableDataAction({\r\n action: >subscribeEmailAction,\r\n input: createInput\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\n\r\nimport { Button, Heading, IModuleProps } from '@msdyn365-commerce-modules/utilities';\r\nimport * as React from 'react';\r\nimport { IDXC_SubscribeNewsletterRealtimeResponse } from '../../data-actions/generated/DataServiceEntities.g';\r\nimport { subscribeEmailAction, SubscribeEmailDataActionInput } from './../../data-actions/subscribe-email/subscribe-email-data';\r\nimport { ICittaUnsubscribeData } from './citta-unsubscribe.data';\r\nimport { ICittaUnsubscribeProps } from './citta-unsubscribe.props.autogenerated';\r\n\r\nexport interface ICittaUnsubscribeViewProps extends ICittaUnsubscribeProps {\r\n unsubscribeContainer: IModuleProps;\r\n alertMessage?: React.ReactNode;\r\n unsubscribeHeading?: React.ReactNode;\r\n unsubscribeInput?: React.ReactNode;\r\n unsubscribeButton?: React.ReactNode ;\r\n}\r\n\r\ninterface ICittaUnsubscribeState {\r\n alertMessage: string;\r\n alertClass: string;\r\n inputEmail: string;\r\n}\r\n\r\n/**\r\n *\r\n * CittaUnsubscribe component\r\n * @extends {React.PureComponent>}\r\n */\r\nclass CittaUnsubscribe extends React.PureComponent, ICittaUnsubscribeState> {\r\n constructor(props: ICittaUnsubscribeViewProps) {\r\n super(props);\r\n this._handleButtonClick = this._handleButtonClick.bind(this);\r\n this._handleInputChange = this._handleInputChange.bind(this);\r\n\r\n this.state = {\r\n alertMessage: '',\r\n alertClass: '',\r\n inputEmail: ''\r\n };\r\n }\r\n\r\n public render(): JSX.Element | null {\r\n const viewProps: ICittaUnsubscribeViewProps = {\r\n ...(this.props as ICittaUnsubscribeProps),\r\n unsubscribeContainer: {\r\n moduleProps: this.props,\r\n className: 'container citta-unsubscribe'\r\n },\r\n alertMessage: this._renderAlertMessage(),\r\n unsubscribeHeading: this._renderUnsubscribeHeading(),\r\n unsubscribeInput: this._renderUnsubscribeInput(),\r\n unsubscribeButton: this._renderUnsubscribeButton()\r\n };\r\n return this.props.renderView(viewProps);\r\n }\r\n\r\n // tslint:disable-next-line: no-any\r\n private _handleInputChange = (event: any) => {\r\n this.setState({\r\n inputEmail: event.target.value\r\n });\r\n }\r\n\r\n private _handleButtonClick = async () => {\r\n const response = await this._callUnsubscribeAPI(this.state.inputEmail);\r\n if (response.Result && response.Message) {\r\n this.setState({\r\n alertMessage: `${response.Message}`,\r\n alertClass: response.Message === 'Unsubscribed successfully.' ? 'alert-green' : 'alert-yellow'\r\n });\r\n }\r\n }\r\n\r\n private async _callUnsubscribeAPI(email: string): Promise {\r\n try {\r\n return await subscribeEmailAction(new SubscribeEmailDataActionInput(email, false), this.props.context.actionContext);\r\n } catch (e) {\r\n throw this.props.telemetry.error(`Something went wrong ------${e}`);\r\n }\r\n }\r\n\r\n private _renderUnsubscribeHeading(): React.ReactNode {\r\n const { unsubscribeHeading } = this.props.config;\r\n return (\r\n \r\n );\r\n }\r\n\r\n private _renderAlertMessage(): React.ReactNode {\r\n const { alertMessage, alertClass } = this.state;\r\n const displayAlert: boolean = (alertMessage ? alertMessage !== '' : false);\r\n return (\r\n <>\r\n {displayAlert ? : null}\r\n >\r\n );\r\n }\r\n\r\n private _renderUnsubscribeInput(): React.ReactNode {\r\n return (\r\n \r\n \r\n
\r\n );\r\n }\r\n\r\n private _renderUnsubscribeButton(): React.ReactNode {\r\n const { resources } = this.props;\r\n return (\r\n \r\n );\r\n }\r\n}\r\n\r\nexport default CittaUnsubscribe;","/*!\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 {\n getPayloadObject,\n getTelemetryAttributes,\n getTelemetryObject,\n IModuleProps,\n INodeProps,\n IPayLoad,\n ITelemetryContent,\n NodeTag,\n TelemetryConstant\n} from '@msdyn365-commerce-modules/utilities';\nimport classnames from 'classnames';\nimport { observer } from 'mobx-react';\nimport * as React from 'react';\n\nimport { createAccordionStateInput } from '../..';\nimport { IAccordionData } from './accordion.data';\nimport { IAccordionProps } from './accordion.props.autogenerated';\n\n/**\n *\n * Accordion component.\n * @extends {React.PureComponent>}\n */\n\nexport interface ICallToActionProps {\n link: INodeProps[];\n}\n\n/**\n * Added interface for state management.\n */\nexport interface IAccordianState {\n isDisabled: boolean;\n}\n\nexport interface IAccordionViewProps extends IAccordionProps<{}> {\n heading?: React.ReactNode;\n AccordionContainer: IModuleProps;\n HeaderSection: INodeProps;\n HeadingWrapper: INodeProps;\n accordianButtonsContainer: INodeProps;\n accordionButtons: React.ReactNode;\n accordionItemContainer: INodeProps;\n accordionItems: React.ReactNode;\n}\n\n/**\n *\n * Accordion component.\n * @extends {React.Component>}\n */\n@observer\nclass Accordion extends React.PureComponent, IAccordianState> {\n private readonly telemetryContent?: ITelemetryContent;\n\n private readonly payLoad: IPayLoad;\n\n private readonly expandAllButtonRef: React.RefObject = React.createRef();\n\n private readonly collapseAllButtonRef: React.RefObject = React.createRef();\n\n constructor(props: IAccordionProps) {\n super(props);\n this._onExpandAll = this._onExpandAll.bind(this);\n this._onCollapseAll = this._onCollapseAll.bind(this);\n this.telemetryContent = getTelemetryObject(\n this.props.context.request.telemetryPageName!,\n this.props.friendlyName,\n this.props.telemetry\n );\n this.payLoad = getPayloadObject('click', this.telemetryContent, '');\n this.state = { isDisabled: false };\n }\n\n public render(): JSX.Element {\n const { slots } = this.props;\n const { heading, className } = this.props.config;\n const headingComponent = heading && heading.text && (\n \n );\n\n const accordionViewProps = {\n ...this.props,\n AccordionContainer: {\n moduleProps: this.props,\n className: classnames('ms-accordion', className)\n },\n HeaderSection: { className: 'ms-accordion-header-section' },\n HeadingWrapper: { className: 'ms-accordion-header-section-container' },\n heading: headingComponent,\n config: this.props && this.props.config,\n accordianButtonsContainer: {\n tag: 'div' as NodeTag,\n className: 'ms-accordion-header-section-toggle-button-container'\n },\n accordionButtons: this._renderAccordionButton(),\n accordionItemContainer: {\n tag: 'div' as NodeTag,\n className: 'ms-accordion-item-section'\n },\n accordionItems:\n slots &&\n slots.accordionItems &&\n slots.accordionItems.length > 0 &&\n slots.accordionItems.map((item: React.ReactNode, index: number) => this._getAccordionItem(item, index))\n };\n return this.props.renderView(accordionViewProps) as React.ReactElement;\n }\n\n public handleHeadingChange = (event: Msdyn365.ContentEditableEvent) => (this.props.config.heading!.text = event.target.value);\n\n private _renderAccordionButton(): React.ReactNode | null {\n const { config, resources } = this.props;\n const { heading } = config;\n this.payLoad.contentAction.etext = TelemetryConstant.ExpandAll;\n const attributeExpandAll = getTelemetryAttributes(this.telemetryContent!, this.payLoad);\n this.payLoad.contentAction.etext = TelemetryConstant.CollapseAll;\n const attributeCollapseAll = getTelemetryAttributes(this.telemetryContent!, this.payLoad);\n if (!config.showToggleAll) {\n this.props.context.telemetry.error('Accordion button content is empty, module wont render');\n return null;\n }\n return (\n <>\n \n \n {resources.toggleAllSeparator}\n \n \n >\n );\n }\n\n private _onExpandAll(): void {\n const accordionState = { isAllExpanded: true };\n this.props.context.actionContext.update(createAccordionStateInput(accordionState), accordionState);\n if (accordionState.isAllExpanded) {\n this.setState({\n isDisabled: true\n });\n setTimeout(() => {\n this.collapseAllButtonRef.current?.focus();\n }, 50);\n }\n }\n\n private _onCollapseAll(): void {\n const accordionState = { isAllExpanded: false };\n this.props.context.actionContext.update(createAccordionStateInput(accordionState), accordionState);\n if (!accordionState.isAllExpanded) {\n this.setState({\n isDisabled: false\n });\n setTimeout(() => {\n this.expandAllButtonRef.current?.focus();\n }, 50);\n }\n }\n\n private _getAccordionItem(item: React.ReactNode, index: number): React.ReactNode {\n return (\n \n {React.cloneElement(item as React.ReactElement, { interactionStyle: this.props.config.interactionStyle })}\n \n );\n }\n}\n\nexport default Accordion;\n","/*!\n * Copyright (c) Microsoft Corporation.\n * All rights reserved. See LICENSE in the project root for license information.\n */\n\nimport { IAccordionExpandedState } from './data-actions/accordion-state';\nimport { createAccordionStateInput } from './data-actions/accordion-state-data-action';\nimport accordion from './modules/accordion/accordion';\nimport { interactionStyle } from './modules/accordion/accordion.props.autogenerated';\nimport accordionView from './modules/accordion/accordion.view';\n\nexport * from './modules/accordion/accordion';\nexport * from './modules/accordion/accordion.view';\n\nexport { accordion, accordionView, createAccordionStateInput, IAccordionExpandedState, interactionStyle };\n"],"sourceRoot":""}