{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///D:/a/1/s/libs/diagnostics/src/AppError/AppErrorTracker.ts","webpack:///D:/a/1/s/libs/isomorphic-util/src/DOMHelpers.ts","webpack:///D:/a/1/s/libs/core/src/constants/Constants.ts","webpack:///D:/a/1/s/libs/core/src/app/HeadData.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/reducers/ActionDispatchHelper.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/reducers/ActionDispatchCancellationToken.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/reducers/ActionSenderBase.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/reducers/ActionSender.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/reducers/GlobalActionSender.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/reducers/ActionMap.ts","webpack:///D:/a/1/s/libs/core/src/utilities/UrlUtility.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/constants/ConnectorConstants.ts","webpack:///D:/a/1/s/libs/isomorphic-util/src/requestData.ts","webpack:///D:/a/1/s/libs/core/src/app/AppEnvironment.ts","webpack:///D:/a/1/s/libs/diagnostics/src/AppError/AppErrors.ts","webpack:///D:/a/1/s/libs/core/src/utilities/Parsing.ts","webpack:///D:/a/1/s/libs/diagnostics/src/logging/Logger.ts","webpack:///D:/a/1/s/libs/core/src/utilities/Utility.ts","webpack:///D:/a/1/s/libs/experiences-constants/src/SignedInStatus.ts","webpack:///D:/a/1/s/libs/milestone-data/src/MilestoneData.actions.ts","webpack:///D:/a/1/s/libs/milestone-data/src/data-model/ExperienceLoadingState.ts","webpack:///D:/a/1/s/libs/experiences-constants/src/AppTypes.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/reducers/DynamicReducer.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/pages/PageHelper.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/pages/PageBase.ts","webpack:///D:/a/1/s/libs/core/src/utilities/CookieUtility.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/pages/index.ts","webpack:///D:/a/1/s/libs/core/src/utilities/WebStorage.ts","webpack:///D:/a/1/s/libs/core/src/app/Environment.ts","webpack:///D:/a/1/s/libs/experiences-base/src/utilities/ColumnWidths.ts","webpack:///D:/a/1/s/libs/render-cache/src/Constants.ts","webpack:///D:/a/1/s/libs/auth/src/AadAuthHelper.ts","webpack:///D:/a/1/s/libs/diagnostics/src/performance/PageTimings.ts","webpack:///D:/a/1/s/libs/experiences-base/src/utilities/BreakpointManager.ts","webpack:///./src/integration/RequireAsync.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/reducers/DataConnectorInjector.ts","webpack:///D:/a/1/s/libs/core/src/app/Enterprise.ts","webpack:///D:/a/1/s/libs/diagnostics/src/performance/AppPerfTrace.ts","webpack:///D:/a/1/s/libs/diagnostics/src/performance/PerfTimeline.ts","webpack:///D:/a/1/s/libs/diagnostics/src/performance/ExperienceDiagnostics.ts","webpack:///D:/a/1/s/libs/experiences-constants/src/ConnectorNamespaces.ts","webpack:///D:/a/1/s/libs/oneservice/src/OneServiceUtility.ts","webpack:///D:/a/1/s/libs/core/src/app/Market.ts","webpack:///D:/a/1/s/components/icon/src/icons/GlyphInline.ts","webpack:///D:/a/1/s/components/icon/src/Icon.props.ts","webpack:///./src/integration/SubnavTabId.ts","webpack:///D:/a/1/s/components/icon/src/index.ts","webpack:///D:/a/1/s/components/icon/src/Icon.styles.ts","webpack:///D:/a/1/s/components/icon/src/Icon.tsx","webpack:///D:/a/1/s/libs/core/src/utilities/WebWorkerUtility.ts","webpack:///D:/a/1/s/libs/core/src/app/HostPage.ts","webpack:///D:/a/1/s/libs/core/src/utilities/ServerCacheMock.ts","webpack:///D:/a/1/s/libs/experiences-constants/src/PageTypes.ts","webpack:///D:/a/1/s/libs/experiences-constants/src/AuthCookieNames.ts","webpack:///./src/integration/MediatorEventNames.ts","webpack:///D:/a/1/s/libs/diagnostics/src/performance/PerfMarker.ts","webpack:///D:/a/1/s/libs/views-helpers/src/IntraArticle.types.ts","webpack:///./src/integration/PrimeTrack.ts","webpack:///./src/integration/PrimeMediator.ts","webpack:///./src/integration/PrimeTrackExtensionComplete.ts","webpack:///./src/integration/PrimeTelemetry.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/reducers/ActionHandler.ts","webpack:///D:/a/1/s/libs/views-helpers/src/ViewsStringResource.ts","webpack:///D:/a/1/s/libs/experiences-base/src/tracking/Telemetry.ts","webpack:///./src/integration/SubnavTabName.ts","webpack:///D:/a/1/s/libs/views-helpers/src/ViewsUtility.ts","webpack:///D:/a/1/s/components/icon/icons/AdChoices.svg","webpack:///D:/a/1/s/components/icon/icons/BingCardDefaultHotelImage.svg","webpack:///D:/a/1/s/components/icon/icons/BingHotelSeePrice.svg","webpack:///D:/a/1/s/components/icon/icons/BingLogo.svg","webpack:///D:/a/1/s/components/icon/icons/BingRatingDarkLightStar.svg","webpack:///D:/a/1/s/components/icon/icons/BingRatingDarkStar.svg","webpack:///D:/a/1/s/components/icon/icons/BingRatingLightStar.svg","webpack:///D:/a/1/s/components/icon/icons/BlowingHail.svg","webpack:///D:/a/1/s/components/icon/icons/BlowingHailWhite.svg","webpack:///D:/a/1/s/components/icon/icons/BlowingSnow.svg","webpack:///D:/a/1/s/components/icon/icons/BlowingSnowWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Check.svg","webpack:///D:/a/1/s/components/icon/icons/Chevron.svg","webpack:///D:/a/1/s/components/icon/icons/CircleClose.svg","webpack:///D:/a/1/s/components/icon/icons/ClearNight.svg","webpack:///D:/a/1/s/components/icon/icons/ClearNightWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Close.svg","webpack:///D:/a/1/s/components/icon/icons/Cloudy.svg","webpack:///D:/a/1/s/components/icon/icons/CloudyWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Copy.svg","webpack:///D:/a/1/s/components/icon/icons/DarkModeHotel.svg","webpack:///D:/a/1/s/components/icon/icons/DayTime.svg","webpack:///D:/a/1/s/components/icon/icons/Delete.svg","webpack:///D:/a/1/s/components/icon/icons/Dislike.svg","webpack:///D:/a/1/s/components/icon/icons/DislikeText.svg","webpack:///D:/a/1/s/components/icon/icons/Disliked.svg","webpack:///D:/a/1/s/components/icon/icons/DislikedLight.svg","webpack:///D:/a/1/s/components/icon/icons/DislikedText.svg","webpack:///D:/a/1/s/components/icon/icons/Docx.svg","webpack:///D:/a/1/s/components/icon/icons/Download.svg","webpack:///D:/a/1/s/components/icon/icons/Edit.svg","webpack:///D:/a/1/s/components/icon/icons/Edited.svg","webpack:///D:/a/1/s/components/icon/icons/Ellipses.svg","webpack:///D:/a/1/s/components/icon/icons/EllipsesLight.svg","webpack:///D:/a/1/s/components/icon/icons/Excel.svg","webpack:///D:/a/1/s/components/icon/icons/Facebook.svg","webpack:///D:/a/1/s/components/icon/icons/FacebookText.svg","webpack:///D:/a/1/s/components/icon/icons/FacebookTextBlack.svg","webpack:///D:/a/1/s/components/icon/icons/Fog.svg","webpack:///D:/a/1/s/components/icon/icons/FogWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Folder.svg","webpack:///D:/a/1/s/components/icon/icons/FolderOpen.svg","webpack:///D:/a/1/s/components/icon/icons/Form.svg","webpack:///D:/a/1/s/components/icon/icons/FreezingRain.svg","webpack:///D:/a/1/s/components/icon/icons/FreezingRainWhite.svg","webpack:///D:/a/1/s/components/icon/icons/GalleryFullscreen.svg","webpack:///D:/a/1/s/components/icon/icons/GalleryMediaIcon.svg","webpack:///D:/a/1/s/components/icon/icons/GenericFile.svg","webpack:///D:/a/1/s/components/icon/icons/GridView.svg","webpack:///D:/a/1/s/components/icon/icons/HailDay.svg","webpack:///D:/a/1/s/components/icon/icons/HailDayWhite.svg","webpack:///D:/a/1/s/components/icon/icons/HailNight.svg","webpack:///D:/a/1/s/components/icon/icons/HailNightWhite.svg","webpack:///D:/a/1/s/components/icon/icons/HazeSmoke.svg","webpack:///D:/a/1/s/components/icon/icons/HazeSmokeWhite.svg","webpack:///D:/a/1/s/components/icon/icons/HeavySnow.svg","webpack:///D:/a/1/s/components/icon/icons/HeavySnowWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Hide.svg","webpack:///D:/a/1/s/components/icon/icons/HideStory.svg","webpack:///D:/a/1/s/components/icon/icons/Hotel.svg","webpack:///D:/a/1/s/components/icon/icons/Information.svg","webpack:///D:/a/1/s/components/icon/icons/InteractionRequiredDark.svg","webpack:///D:/a/1/s/components/icon/icons/InteractionRequiredLight.svg","webpack:///D:/a/1/s/components/icon/icons/Interested.svg","webpack:///D:/a/1/s/components/icon/icons/LightRain.svg","webpack:///D:/a/1/s/components/icon/icons/LightRainWhite.svg","webpack:///D:/a/1/s/components/icon/icons/LightSnow.svg","webpack:///D:/a/1/s/components/icon/icons/LightSnowWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Like.svg","webpack:///D:/a/1/s/components/icon/icons/LikeText.svg","webpack:///D:/a/1/s/components/icon/icons/Liked.svg","webpack:///D:/a/1/s/components/icon/icons/LikedText.svg","webpack:///D:/a/1/s/components/icon/icons/Line.svg","webpack:///D:/a/1/s/components/icon/icons/LinkedIn.svg","webpack:///D:/a/1/s/components/icon/icons/LinkedInBlack.svg","webpack:///D:/a/1/s/components/icon/icons/LinkedInText.svg","webpack:///D:/a/1/s/components/icon/icons/Mail.svg","webpack:///D:/a/1/s/components/icon/icons/MailBlack.svg","webpack:///D:/a/1/s/components/icon/icons/ManagedBriefcase.svg","webpack:///D:/a/1/s/components/icon/icons/Message.svg","webpack:///D:/a/1/s/components/icon/icons/Messages.svg","webpack:///D:/a/1/s/components/icon/icons/MicrosoftNews.svg","webpack:///D:/a/1/s/components/icon/icons/MicrosoftNewsFull.svg","webpack:///D:/a/1/s/components/icon/icons/MicrosoftNewsFull_FR.svg","webpack:///D:/a/1/s/components/icon/icons/MicrosoftNewsFull_ZH.svg","webpack:///D:/a/1/s/components/icon/icons/ModerateRain.svg","webpack:///D:/a/1/s/components/icon/icons/ModerateRainWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Movie.svg","webpack:///D:/a/1/s/components/icon/icons/NightTime.svg","webpack:///D:/a/1/s/components/icon/icons/OfficeFormsLogo.svg","webpack:///D:/a/1/s/components/icon/icons/OneDrive.svg","webpack:///D:/a/1/s/components/icon/icons/OneNote.svg","webpack:///D:/a/1/s/components/icon/icons/Onetoc.svg","webpack:///D:/a/1/s/components/icon/icons/Outlook.svg","webpack:///D:/a/1/s/components/icon/icons/PartlyCloudyDay.svg","webpack:///D:/a/1/s/components/icon/icons/PartlyCloudyDayWhite.svg","webpack:///D:/a/1/s/components/icon/icons/PartlyCloudyNight.svg","webpack:///D:/a/1/s/components/icon/icons/PartlyCloudyNightWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Pdf.svg","webpack:///D:/a/1/s/components/icon/icons/People.svg","webpack:///D:/a/1/s/components/icon/icons/Pin.svg","webpack:///D:/a/1/s/components/icon/icons/PowerPoint.svg","webpack:///D:/a/1/s/components/icon/icons/Pptx.svg","webpack:///D:/a/1/s/components/icon/icons/RainShowersDay.svg","webpack:///D:/a/1/s/components/icon/icons/RainShowersDayWhite.svg","webpack:///D:/a/1/s/components/icon/icons/RainShowersNight.svg","webpack:///D:/a/1/s/components/icon/icons/RainShowersNightWhite.svg","webpack:///D:/a/1/s/components/icon/icons/RainSnow.svg","webpack:///D:/a/1/s/components/icon/icons/RainSnowShowersDay.svg","webpack:///D:/a/1/s/components/icon/icons/RainSnowShowersDayWhite.svg","webpack:///D:/a/1/s/components/icon/icons/RainSnowShowersNight.svg","webpack:///D:/a/1/s/components/icon/icons/RainSnowShowersNightWhite.svg","webpack:///D:/a/1/s/components/icon/icons/RainSnowWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Refresh.svg","webpack:///D:/a/1/s/components/icon/icons/Remove.svg","webpack:///D:/a/1/s/components/icon/icons/Save.svg","webpack:///D:/a/1/s/components/icon/icons/Saved.svg","webpack:///D:/a/1/s/components/icon/icons/Search.svg","webpack:///D:/a/1/s/components/icon/icons/Share.svg","webpack:///D:/a/1/s/components/icon/icons/ShareLight.svg","webpack:///D:/a/1/s/components/icon/icons/Sharepoint.svg","webpack:///D:/a/1/s/components/icon/icons/Skype.svg","webpack:///D:/a/1/s/components/icon/icons/SkypeOffice.svg","webpack:///D:/a/1/s/components/icon/icons/SnowShowersDay.svg","webpack:///D:/a/1/s/components/icon/icons/SnowShowersDayWhite.svg","webpack:///D:/a/1/s/components/icon/icons/SnowShowersNight.svg","webpack:///D:/a/1/s/components/icon/icons/SnowShowersNightWhite.svg","webpack:///D:/a/1/s/components/icon/icons/SunnyDay.svg","webpack:///D:/a/1/s/components/icon/icons/SunnyDayWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Sway.svg","webpack:///D:/a/1/s/components/icon/icons/SwayApp.svg","webpack:///D:/a/1/s/components/icon/icons/Teams.svg","webpack:///D:/a/1/s/components/icon/icons/ThumbnailView.svg","webpack:///D:/a/1/s/components/icon/icons/Thunderstorms.svg","webpack:///D:/a/1/s/components/icon/icons/ThunderstormsWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Trending.svg","webpack:///D:/a/1/s/components/icon/icons/Twitter.svg","webpack:///D:/a/1/s/components/icon/icons/TwitterBlack.svg","webpack:///D:/a/1/s/components/icon/icons/TwitterText.svg","webpack:///D:/a/1/s/components/icon/icons/Unpin.svg","webpack:///D:/a/1/s/components/icon/icons/Upload.svg","webpack:///D:/a/1/s/components/icon/icons/VerticalSeparator.svg","webpack:///D:/a/1/s/components/icon/icons/VideoMediaIcon.svg","webpack:///D:/a/1/s/components/icon/icons/VideoPlay.svg","webpack:///D:/a/1/s/components/icon/icons/Visio.svg","webpack:///D:/a/1/s/components/icon/icons/Vsdx.svg","webpack:///D:/a/1/s/components/icon/icons/WeatherAlert.svg","webpack:///D:/a/1/s/components/icon/icons/WhatsApp.svg","webpack:///D:/a/1/s/components/icon/icons/WhatsAppBlack.svg","webpack:///D:/a/1/s/components/icon/icons/Windy.svg","webpack:///D:/a/1/s/components/icon/icons/WindyWhite.svg","webpack:///D:/a/1/s/components/icon/icons/Word.svg","webpack:///D:/a/1/s/components/icon/icons/World.svg","webpack:///D:/a/1/s/components/icon/icons/Xlsx.svg","webpack:///D:/a/1/s/components/icon/icons/Yammer.svg","webpack:///D:/a/1/s/libs/experiences-base/src/tracking/Telemetry.types.ts","webpack:///D:/a/1/s/libs/core/src/PublicPath/index.ts","webpack:///./src/publicPath.ts","webpack:///D:/a/1/s/libs/core/src/config/configs/ExperienceState.ts","webpack:///D:/a/1/s/libs/core/src/config/configs/ChildExperiencesDeferRenderType.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/actions/CommonActions.ts","webpack:///D:/a/1/s/libs/core/src/config/configs/ChildExperienceValidator.ts","webpack:///D:/a/1/s/libs/config-validator/src/ConfigProcessor.ts","webpack:///D:/a/1/s/libs/experiences-connector/src/experience-loader/ExperienceLoader.ts","webpack:///D:/a/1/s/libs/experiences-connector/src/connectors/ComponentConnector.ts","webpack:///D:/a/1/s/libs/experiences-connector/src/connectors/ExperiencePerfTimeline.tsx","webpack:///./src/integration/Constants.ts","webpack:///./src/integration/Mediator.ts","webpack:///D:/a/1/s/libs/render-cache/src/Helper.ts","webpack:///D:/a/1/s/libs/core/src/telemetry-base/TelemetryBase.ts","webpack:///D:/a/1/s/libs/core/src/services/ExponentialBackoffRetry.ts","webpack:///D:/a/1/s/libs/oneservice/src/ServiceRequest.ts","webpack:///D:/a/1/s/libs/experiences-base/src/utilities/FastBreakpointManager.ts","webpack:///D:/a/1/s/libs/oneservice/src/UrlUtility.ts","webpack:///./src/integration/SubnavTabHelper.ts","webpack:///D:/a/1/s/libs/core/src/bundles/Bundles.ts","webpack:///D:/a/1/s/libs/experimentation-helpers/src/GetPeregrineFlights.ts","webpack:///D:/a/1/s/libs/core/src/config/Resolver.ts","webpack:///D:/a/1/s/libs/core/src/utilities/IndexedDb.ts","webpack:///D:/a/1/s/libs/core/src/utilities/ServerCache.ts","webpack:///D:/a/1/s/libs/experiences-redux/src/connectors/DataConnector.ts","webpack:///D:/a/1/s/libs/milestone-data/src/data-model/ExperienceDeferralHandlerSignature.ts","webpack:///D:/a/1/s/libs/milestone-data/src/data-model/ExperienceMilestoneEventTypes.ts","webpack:///D:/a/1/s/libs/core/src/config/configs/ExperienceCompositionTypes.ts","webpack:///D:/a/1/s/libs/core/src/config/configs/composition/ChildrenTypes.ts","webpack:///D:/a/1/s/libs/core/src/app/ScreenWidth.ts","webpack:///D:/a/1/s/libs/milestone-data/src/data-model/ExperienceDeferralEventTypes.ts","webpack:///D:/a/1/s/libs/milestone-data/src/MilestoneData.Constants.ts","webpack:///D:/a/1/s/libs/milestone-data/src/data-management/ExperienceDeferralDependencyTracker.ts","webpack:///D:/a/1/s/libs/milestone-data/src/MilestoneData.Helper.ts","webpack:///D:/a/1/s/libs/diagnostics/src/performance/PerfTracker.ts","webpack:///D:/a/1/s/libs/experiences-base/src/base/BaseExperience.tsx","webpack:///D:/a/1/s/libs/diagnostics/src/performance/PerfMarkerConstants.ts","webpack:///D:/a/1/s/libs/diagnostics/src/performance/PerfMarkerWait.ts","webpack:///D:/a/1/s/libs/views-helpers/src/SocialMediaConfig.ts","webpack:///D:/a/1/s/components/pop-over/src/PopOver.tsx","webpack:///D:/a/1/s/components/pop-over/src/PopOver.styles.ts","webpack:///D:/a/1/s/components/pop-over/src/index.ts","webpack:///D:/a/1/s/libs/core/src/utilities/ZIndex.ts","webpack:///D:/a/1/s/libs/core/src/services/ImageServiceConfig.ts","webpack:///D:/a/1/s/components/card-context-menu/src/index.ts","webpack:///D:/a/1/s/components/card-context-menu/src/CardContextMenu.style.ts","webpack:///D:/a/1/s/components/card-context-menu/src/CardContextMenu.tsx","webpack:///D:/a/1/s/components/social-media-icon/src/SocialMediaIcon.styles.ts","webpack:///D:/a/1/s/components/social-media-icon/src/index.ts","webpack:///D:/a/1/s/components/social-media-icon/src/SocialMediaIcon.tsx","webpack:///D:/a/1/s/libs/core/src/utilities/ShallowCompare.ts","webpack:///D:/a/1/s/components/share-dialog/src/ShareDialog.styles.ts","webpack:///D:/a/1/s/components/share-dialog/src/StringResource.ts","webpack:///D:/a/1/s/components/share-dialog/src/ShareDialog.tsx","webpack:///D:/a/1/s/components/share-dialog/src/index.ts","webpack:///D:/a/1/s/components/article-card/src/ArticleCard.tsx","webpack:///D:/a/1/s/libs/views-helpers/src/SocialMediaHelper.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/ContentActionsToolbar.constants.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/components/sharing-toolbar/SharingToolbar.props.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/ContentActionsToolbar.actions.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/components/sharing-toolbar/SharingToolbar.constants.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/ContentActionsToolbar.inspector.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/services/ContentActionsToolbarServiceClient.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/ContentActionsToolbar.telemetry.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/ContentActionsToolbar.connector.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/ContentActionsToolbar.props.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/ContentActionsToolbar.reducer.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/components/sharing-toolbar/SharingToolbar.styles.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/components/dialog-article-card/DialogArticleCard.tsx","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/components/dialog-article-card/DialogArticleCard.styles.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/components/dialog-article-card/index.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/components/sharing-toolbar/index.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/components/sharing-toolbar/SharingToolbar.tsx","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/ContentActionsToolbar.tsx","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/ContentActionsToolbar.styles.ts","webpack:///D:/a/1/s/experiences/content-actions-toolbar/src/index.ts","webpack:///./src/content-actions-toolbar/ContentActionsToolbar.ts"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","14","exports","module","l","e","promises","installedChunkData","promise","Promise","resolve","reject","onScriptComplete","script","document","createElement","charset","timeout","nc","setAttribute","src","p","jsonpScriptSrc","error","Error","event","onerror","onload","clearTimeout","chunk","errorType","type","realSrc","target","message","name","request","undefined","setTimeout","head","appendChild","all","m","c","d","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","oe","err","console","jsonpArray","window","oldJsonpFunction","slice","Severity","canUseDOM","getLocationHref","location","href","url","getLocationHostname","hostname","getLocationHost","host","getLocationOrigin","origin","getLocationSearch","search","getLocationProtocol","protocol","getDocumentElementById","elementId","getElementById","getDocumentElementsByTagName","tagName","getElementsByTagName","getIndexedDB","indexedDB","getInnerWidth","innerWidth","getInnerHeight","innerHeight","getDevicePixelRatio","devicePixelRatio","ariaLabelAttribute","rootElementId","htmlElementIds","html","body","applicationCacheConstants","manifestAttributeName","pagesRefreshData","storedHeadDataKey","storedLastUsedActivityIdKey","clientSettings","pagetypeSettings","info","js","lang","dir","serviceUrl","telemetryId","trackPageProduct","trackPageType","minimumHostPagePathSegments","appAnonCookieExistsCookieName","childCookieName","oneServiceQueryStringKeys","activityId","apiKey","complexInfoPaneEnabled","contentType","disableTypeSerialization","infopaneCount","fdhead","feedLayoutRequestType","filter","ids","market","ocid","parentContentId","parentNamespace","parentTitle","query","queryType","qScope","responseSchema","select","signInCookieName","skip","source","timeOut","top","user","wrapOData","AriaRoles","EnterpriseOneServiceApi","EnterpiseFlightId","OfficeDefaultPivotFlightId","HeadData","this","initializeHeadData","locale","marketDir","currentFlights","userIsSignedIn","isPreload","isAppcache","isEnterprise","isOfficeDefaultPivot","isServiceWorkerCache","anonCookieName","ssoComplete","aadState","_instance","locationSearch","htmlElement","headElement","initializeFromDom","getAttribute","initializeFromStorage","navigator","serviceWorker","controller","updateStorageActivityId","language","toLowerCase","toLocaleLowerCase","includes","flights","getParamsWithItems","find","item","headDataJs","headJs","anonckname","signedin","getQueryParameterByName","IsEnterprise","audienceMode","Enterprise","IsOfficeDefaultPivot","storedActivities","getItem","storedActivityIds","headData","ClientSettings","pagetype","dataClientSettings","pageTypeFromSettings","setFlights","responseFromStorage","parsedResponseFromStorage","currentPageStoredHeadData","storedClientSettings","storedFlights","aid","existingLastUsedActivityIds","currentPageLastUsedActivityId","id","previouslyUsed","activityIdToStore","ts","Date","getTime","setItem","JSON","stringify","flightString","exec","getHeadData","getInstance","getActionPayload","connector","args","experienceInstanceId","stateKey","namespace","params","dispatchAction","payload","store","dispatch","PageBase","ActionDispatchCancellationToken","isCancelled","cancellationToken","isCancellationRequested","observers","perfTimeline","tryGetPerfTimeline","actionEndMeasure","startMeasure","endMeasure","dispatchResult","getDispatchResult","Array","arguments","forEach","observer","log","renderActionPayload","ConnectorConstants","renderAction","super","connectorInstance","rootReducer","UrlUtility","primeForbiddenCharacters","getParamsFromUrl","decodeComponents","getParams","split","decodeURIComponentWithPlusSign","val","replace","decodeURIComponent","queryString","queryArray","ndx","parts","queryKey","queryValue","newParam","existingParam","entry","encodeURIComponentForPrime","uriComponent","encodeURIComponent","startsWith","substring","queryItems","paramsObj","paramArray","keyValuePair","getParamsObj","isValidUrl","validateScheme","indexOf","keyValueArrayToQueryString","kv","isKeyValuePair","map","join","joinSubpathToURL","subPath","trimmedEndSlashFromHref","trimmedStartSlashFromSubpath","URL","updateSearchParam","searchParams","set","appendSearchParam","fallback","append","getAbsoluteUrl","partialUrl","connectorStateKey","dataConnectorMergeInitAction","RequestData","canUseCssGrid","requestId","global","resetRequestData","resetInstance","getRequestData","AppEnvironment","initializeAppEnvironment","environmentConfigUrl","process","env","WEBPACK_DEV_SERVER","URLSearchParams","searchParam","contentServiceUrlBase","currentRequestTargetScope","currentMarket","environment","hostPage","appType","authCookieName","accountType","aadData","isDebug","showMnsCreatorDashboard","currentContentLinkHost","serviceUrlBase","feedServiceUrlBase","isFrePage","rootTelemetryId","trackInfo","userId","disableCachingConfigs","enableConfigService","isMultiConfigRetrievalEnabled","disableContentPreviewCache","queryParamOverride","disableContentCacheIDBRead","configServiceBaseUrl","featureFlags","configRootUrl","cacheBustingIdentifier","countryCode","latitude","longitude","_serviceUrl","environmentFromHeadData","tryReformatGuid","Locale","apps_locale","geo_country","geo_lat","geo_long","setAccountType","apptype","getAuthCookieName","cbid","rootElement","locationHref","locationOrigin","envQSOverwrite","prod","feedBaseDomain","getHostPageFromUrl","muidCookie","Number","trackPageProd","trackPageTypeVal","sitePage","page_product","page_type","createContentLinkHost","setTargetScope","useMultiConfigsRetrieval","getConfigServiceBaseUrl","relativePath","int","urlQuery","param","Hub","MicrosoftNews","Views","Anon","Edge","EdgeChromium","MMX","Office","AppAnon","chrome","authPrivate","getPrimaryAccountInfo","accountInfo","AccountType","SignedOut","account_type","AAD","setAadData","MSA","tokenAcquireParameters","account_id","client_id","scope_or_resource","acquireAccessTokenSilently","acquireResult","AadData","token","access_token","errorInfo","error_info","isSuccess","is_success","isValid","is_token_valid","ZHCN","guid","matches","match","Kids","browser","deviceFormFactor","domain","os","platform","Web","pageType","stringHasData","CurrentFlights","pageExperiments","getAppEnvironment","appEnvironment","severity","Alert","pb","build","BUILD_NUMBER","ServiceUiError","OneServiceCardProviderAppErrors","NoAlert","OneServiceResponseWasNullOrErroneous","ErrorFetchingOneServiceResponse","HighImpact","InvalidJsonInOneServiceResponse","InvalidFeedListInOneServiceResponse","RiverConfigurationIssue","QueryInterestContentFetchError","StaticContentLoaded","ContentPreviewAppErrors","ErrorWhileFetchingContentPreviewContent","InvalidResponseFromContentPreviewFetch","InvalidResponseFromContentPreviewResponseJson","ErrorWhileInitializingAsyncContentPreviewContent","InvalidOrMissingContentId","MissingDataForExternalContent","RiverAppErrors","UnknownMetadataReceivedFromRiverCardProvider","RiverContentProviderFetchException","UnableToSelectSectionTemplateForGivenChildExperiences","InvalidConfig","ChildLoadError","InitialDataLoadError","UserInitiatedPageRefreshErrors","Default","SportsCardError","SportsLeaguePdpFetchError","SportsLeaguePdpInvalidResponse","SportsPlayersPdpFetchError","SportsPlayersPdpInvalidResponse","SportsTeamsPdpFetchError","SportsTeamsPdpInvalidResponse","SportsCardConfigFetchError","SportsCardGetFavoriteTeamDataError","SportsCardGetPlayerBioError","SportsCardGetLeaguesGamesArrayError","SportsCardGetPdpDataFailure","SportsCardGetLeagueSeasonYearDataFailure","SportsCardGetLocalizedTeamNameDataFailure","SportsCardGetTeamDataFailure","SportsCardGetLeagueDataFailure","MoneyCardError","MoneyQuoteSummaryGetError","MoneyQuoteSummariesGetError","MoneyPdpDataGetErrorFromService","MoneyPdpInvalidResponseFromService","MoneyQuoteSummaryGetErrorFromService","MoneyQuoteSummaryInvalidResponseFromService","TrendingNewsErrors","DataFetchError","BackupDataFetchError","GridSectionAppErrors","GridSectionCardGenerationError","CoachmarkAppErrors","GeneralError","NotPlaceable","NotFoundComponent","CoachmarkDataConnectorUndefined","CoachmarkDataAppErrors","InvalidCoachmarkMessage","IrisDataConnectorUndefined","NoSurfaceFoundForCampaign","ErrorFoundForSurface","TelemetryInfoUndefined","EventTypeUndefined","SpotlightPreviewAppErrors","ErrorWhileFetchingSpotlightPreviewCardInfo","NoServiceContextMetadata","SpotlightErrors","UnknownError","ContentFetchError","CardActionErrors","CardActionBaseExperienceError","CardActionPostActionError","CardActionDeleteActionError","CardActionGetActionError","CookieRelatedErrors","SharedStateConnectorNull","OverlayErrors","LoadExperienceError","ViewsCommonAppErrors","InvalidIntraArticleDataError","InvalidDocumentContentError","ViewsPaddleDataLoadError","ViewsErrorPage","ProviderMapperError","ContentActionsToolbarAppErrors","ContentActionsSharingToolbarLoadError","ContentActionsArticleDatafetchError","ContentActionsBaseExperienceError","ContentActionsGetDocumentDataError","ContentActionsGetContentStatusActionError","ContentActionsDeleteActionError","ContentActionsPostActionError","ContentActionsExperienceLoadError","ContentActionsFlipToolbarError","ContentActionsContentStatusFetchError","ContentActionsContentPreviewFetchError","ContentSharingToolbarAppErrors","ContentSharingToolbarInitializationError","ContentProviderAppErrors","InvalidSourceIdError","ProviderDetailsFetchError","ProviderFeedFetchError","InvalidLayoutTemplate","ViewsGalleryAppErrors","InvalidGalleryIdError","GalleryDataLoadError","GalleryImagesLoadError","VideoListAppErrors","VideoListDataLoadError","ViewsArticleAppErrors","InvalidArticleIdError","ArticleDataLoadError","IntraArticleComponentLoadError","InlineGalleryInvokeError","InterestsSearchAppErrors","ErrorResponseFromOneService","ErrorResponseFromOneServiceIsInvalid","InvalidUrlFoundForElement","SelectedItemNotFoundInSuggestions","SelectedItemIsInvalid","InterestsAppErrors","InterestsRetrieveTopicsError","InterestsRetrieveFollowedTopicsError","InterestsRetrieveMutedPublishersError","InterestsUnMutePublisherError","InterestsFollowTopicError","InterestsUnfollowTopicError","InterestsTopicStateUndefined","InterestsShouldHaveRendered","InterestsRetrieveTopicError","InterestsRetrieveSavedStoriesError","InterestsSavedStoriesInvalidConfigError","InterestsSavedStoriesChildLoadError","InterestsSavedStoriesInvalidJsonError","InterestsSavedStoriesInvalidListError","InterestsRetrieveRecommendedTopicsError","UndefinedTopicDataConnector","InterestsRetrieveReadStoriesError","InterestsReadStoriesInvalidConfigError","InterestsReadStoriesChildLoadError","InterestsReadStoriesInvalidJsonError","InterestsReadStoriesInvalidListError","FailedRestoringDefaultTopicsError","ComponentConnectorAppErrors","DuplicateChildInstanceFound","BundleLoadError","ChildConfigInfoListNull","ListStartPositionInvalid","ChildDelayLoadError","ExperienceDependencyTimeout","ExperienceLoaderAppErrors","InsufficientLoadArgs","SearchError","PollsCardAppErrors","PollsListFetchError","PollDataFetchError","PollsCardInvalidPoll","PollsCardInvalidQuizPoll","PollsCardVoteError","PollsCardMapStateToPropsError","PollsUnknownError","MonetizationAppErrors","PlacementManagerLoadError","ArrangementPositionLoadError","GetCMSContentError","GetSAMRTBResponseError","MediaNetEOABError","InvalidPromoModuleConfig","CookieSyncDownloadExternalScriptError","CookieSyncMissingExternalScriptUrl","CookieSyncTimeout","CookieSyncPartnerScriptError","CookieSyncPixelPartnerDownloadError","CMSOrBackfillNativeAdLoadError","MissingRequiredPropertyPlacementManagerConfig","NativeAdTargetScopeError","RiverVideoAdPartnerError","JsTrackerPartnerScriptLoadError","ViglinkError","MissingTopicId","TopicIdNotFound","GetSAMRTBResponseErrorNoAlert","DisplayAdsOathLoadError","DisplayAdsApnLoadError","DisplayAdsApnEmptyProvider","DisplayAdsAdsDetectionNotInit","DisplayAdsMoatLoadError","DisplayAdsNoAdObjects","DisplayAdsProviderIdEncode","TaboolaRiverAppErrors","TaboolaRiverFetchError","CoreLibAppErrors","DeprecatedCompositionLayoutUsed","InvalidColumnInGridConfig","ErrorLoadingBundle","GenericJSException","ResolverAppErrors","IndexedDbWriteFailed","IndexedDbReadFailed","CrsFetchFailed","ReceivedConfigFromCdnAsCrsFetchFailed","GetConfigException","IndexedDbBulkReadFailed","IndexedDbFailedToRemoveCachedConfig","IndexedDbFailedToClearAllCachedConfigs","RenderCachePurgedDueToChangesInConfig","FailedToPurgeRenderCache","RefreshConfigCacheFailed","IndexedDbInitFailed","BingCardsAppErrors","BingCardGetHotelAnswersError","BingCardGetHotelErrorFromService","BingCardGetAnswersError","BingCardInvalidEntityType","BingCardErrorOut","BingAnswersAppErrors","FailedToLoadData","NoCardsContentType","NoCardsRelated","BingShoppingLifestyleCardError","LifestyleShopCardServiceFetchError","LifestyleShopCardServiceFetchInvalidResponse","LifestyleShopCardServiceEmptyResponse","LifestyleShopCardServiceInvalidResponse","LifestyleShopCardCdnServiceFetchError","LifestyleShopCardCdnServiceFetchInvalidResponse","LifestyleShopCardCdnServiceInvalidResponse","LifestyleShopAutosuggestServiceFetchError","LifestyleShopAutosuggestServiceFetchInvalidResponse","LifestyleShopAutosuggestServiceEmptyResponse","LifestyleShopAutosuggestServiceInvalidResponse","LifestyleShopAutosuggestInvalidSuggestionUrl","OneServiceContentDataConnector","FailedToUpdateBypassValueConnectorNotInitialized","FailedToGetBypassValueConnectorNotInitialized","NotificationBellErrors","JsonParseError","RecommendedSearchErrors","ResponseParsingFailed","InvalidJsonResponse","ServiceCallFailed","RenderFailed","Timeout","ElectionResultMapConnectorErrors","ElectionResultMapInspectorErrors","EmptyResultSummaryError","ElectionResultMapErrors","FetchAndUpdateElectionDataError","ElectionDelegateCounterErrors","WebWorkerErrors","FileNotFound","RuntimeError","MessageTimeout","HandledError","IrisErrors","IrisUnknown","InvalidQParams","ArcCallFailed","ArcResponseNotOk","ArcResponseUnparsable","MissingAppEnv","UnknownIrisErrorFound","TimeoutIrisErrorFound","TemplateIrisErrorFound","ClientErrorIrisErrorFound","DSourceIrisErrorFound","ActionCallFailure","ActionFetchFailure","ActionResponseFailure","UncaughtErrorDetected","UnconvertableCreative","InvalidResponseFormat","AbortErrorDiscovered","UnparsableSingleResponseJSON","IrisDataConnectorErrors","SubscriberNotFound","CreativeCountNegativeOrZero","ErrorFetchingSurfaceInfo","SubscriberNotFoundInIrisPlacementDictionary","tryParseJson","jsonString","parse","tryParseInt","defaultValue","parseInt","isNaN","Logger","setupBrowserEnvironment","isDebugEnabled","webpackRequire","setupNodeEnvironment","windowObj","logger","Info","Browser","setupLogLevel","NodeJs","getMessage","infoCallback","setLevel","setupAppenders","removeAllAppenders","addAppender","getLevel","nameRegEx","queryNameValueMatches","RegExp","defaultInstance","Utility","isNotNullOrUndefined","isDefined","potentialKeyValuePair","isKey","isValue","isNonNullObject","isNotNull","isNullOrWhiteSpace","trim","toNumber","arrayHasData","constructor","objectToString","firstRun","attribute","SignedInStatus","AadAccountType","MilestoneDataActions","updateAboveTheFoldVisuallyReady","updateBelowTheFoldTransitionStart","updateExperienceLoadDeferralState","updateExperienceCurrentState","updateExperienceRenderDeferralState","updateInitTiming","updatePageComplete","updateRenderTiming","updateVisuallyReadyTiming","updateDomCompleteTiming","updateMilestonePlugins","ExperienceLoadingState","AppType","_connectorMap","_globalConnectors","_allConnectors","_getDataConnectorPendingPromises","Map","reduce","dataConnector","pendingPromise","resolveCallback","rejectCallback","state","actionPayload","newState","stateChanged","typeIsString","endsWith","statePropertyKey","connectorState","experienceFullNamespace","dataConnectorName","initializeExperience","isGlobal","merge","connectorReducerResult","computeNextStateForConnector","reportStateChange","keys","fullNamespace","has","delete","connectorPreviousState","nextStateForConnector","subReduce","reducer","connectorStateChanged","previousState","reducedState","designSystemMap","WeakMap","designSystemIndexMap","createGenerateClassName","designSystem","callback","dsName","dsIndex","rulesMap","rule","sheet","enhancer","middlewares","__REDUX_DEVTOOLS_EXTENSION_COMPOSE__","trace","traceLimit","_rootReducer","initialState","needsHydrate","_store","connectors","onApplicationStart","connectedTopLevelElement","hostElement","updateJssManagerInstance","pageTimings","hydrate","render","jssInstance","plugins","jss","savedMuid","getCookie","cookie","getMuidCookie","setRequireFunctionalCookie","expiryDays","path","secure","expiryDate","builder","date","setTime","toUTCString","WebStorage","storage","supported","parsedObj","index","removeItem","logError","matchingKeys","storageKey","localStorage","ex","sessionStorage","Environment","getEnvironmentFromString","int1","intpr","intpef","Size1ColumnWidth","Size2ColumnWidth","Size3ColumnWidth","Size4ColumnWidth","GutterSize","storagePrefix","expirationPrefix","renderCacheKey","renderCacheExpirationKey","defaultExpirationTimeMs","riverRcClassName","aadTokenQsKey","aadTokenQsVal","useEnterpriseCompliance","sharedStateConnector","SharedState","getCurrentState","useEnterpriseDomain","_pageTimings","getPageTimings","ColumnArrangement","minViewportWidthOverrides","ColumnArrangementDefinition","arrangement","contentSizePx","isFirstBreakpoint","widthOverride","contentBufferPx","columnArrangements","c1","c2","c3","c4","columnArrangementMap","columnArrangementDefinition","getMediaQuery","minArragement","maxArrangement","queries","minWidthPx","minViewportWidthPx","maxArrangementDefinition","maxArrangementIndex","getMediaQueryFor","columnArrangement","getMediaQuerySelector","mediaQuery","getMediaQuerySelectorFor","requireAsync","moduleName","defaultModule","require","dataConnectorToExperienceKeyMap","createStatePropertyKey","dataConnectorInjector","registerInjection","experienceSet","Set","add","appState","experienceStatePropertyKey","initialDataConnectorState","dataConnectorNamespace","newDataConnectorState","experienceKeys","experienceKey","experiencePreviousState","clientId","oneServiceScope","chromeMetadata","metadataType","pid","threadId","metadata","ph","tid","chromeInstantMarker","category","timeStampMs","chromeMarker","auxData","marker","cat","calculateTimelines","measures","async","timelineGroups","groupBy","measure","timelineName","timelineList","maxValue","groupName","timeline","sort","info1","info2","from","Math","max","to","timeline1","timeline2","mergePageTimings","asyncExperiences","matchRegex","startSuffixRegex","endSuffixLookup","processedKeysToRemove","startSuffixMatch","measureName","endKey","endValue","thisTimelineName","prefixSuffixMatch","keyToRemove","tryCreateAsyncPID","nextPID","KeyCounter","timelineCount","count","getCount","timelineKeyCount","startSuffix","endSuffix","instanceId","addPerfMarks","addPageTimings","markerCount","qualifyKey","oldMeasureName","qualifyMeasureName","newMeasureName","coreMarkerName","dynamicMeasureName","startTime","performance","now","timelineNameAtStart","measureNameCore","formatMeasureName","startMarkerName","singleMark","updatedDynamicMeasureName","endTime","endMarkerName","funcName","func","bindingContext","_this","promiseName","getPromise","coreMeasureName","dynamicMeasureSuffix","markerName","mark","startMarker","endMarker","experiencesForPerf","experiencesExcludedForPerf","addPerformanceMarks","trackAllExp","enablePerfTimeline","perfTimelineInstances","experienceName","shouldTrackPerfTimeline","instanceKey","getInstanceKeyCore","renamePerfTimeline","newExperienceName","oldInstanceKey","getInstanceKey","rename","newInstanceKey","getExperienceMeasures","pageMeasures","getPageMeasures","_getAppPerfTrace","nonZeroResources","getEntriesByType","duration","regex","resourceGroup","remainingResources","entryIndex","pathname","mergeResourceTimings","destinationMeasures","sourceMeasures","mergePageMeasures","_appTimings","chromeTrace","key1","key2","sort_index","timelineIndex","measureIndex","substr","fromMs","toMs","showInParentThread","chromeAsyncMeasure","dur","chromeSyncMeasure","expPerfQsp","expName","expPerfSkipQsp","initExperienceDiagnostics","ConnectorNamespaces","OneServiceUtility","getOneServiceParamsWithoutAuth","ocidSpecifier","addPageInfoToOcid","ActivityId","getOneServiceOCID","TrackInfo","CurrentMarket","runningExperiments","authenticationTicketType","signedInCookieNameHeader","userLocationHeader","serviceRequestOnComplete","serviceRequest","callbackMethod","getOneServiceParamsWithAuth","AuthCookieName","toUpperCase","getOneServiceHeaders","headers","aadToken","getLocationParams","Latitude","Longitude","getBaseRequestData","method","getCommonParams","UserIsSignedIn","UserId","Market","DoubleTap","EmptyMruDark","EmptyMruLight","EmptyPinnedDark","EmptyPinnedLight","EmptySharedDark","EmptySharedLight","NotificationFivePlusSign","NotificationRefreshArrow","SubnavTabId","icon","icon_inline","width","height","props","handledProps","ariaLabel","fill","glyphType","managedClasses","onError","wrapperClassName","fallBackInlineComponent","default","role","style","className","generateClassNames","title","IconComponent","lazy","then","ReactComponent","catch","attrProps","Suspense","isWebWorkerPresent","messages","logAppError","getFromWebWorker","timeoutInMs","defaultResponse","fetched","promiseTimeout","timeOutPromise","endGetFromWebWorker","errorMessage","customMessage","webWorkerPromise","response","webWorker","postMessage","race","sendToWebWorker","subscribeWebWorkerNotification","override","_isWebWorkerPresent","onmessage","pendingMessage","HostPage","pathnameSegments","topDomainName","originalUrl","categoryKey","verticalKey","hostName","topDomain","indexOffset","subcategoryKey","MockLRUCache","cacheMap","maxAge","PageType","AudienceModeType","AuthCookieExistsCookieName","MediatorEventNames","ContentActionsUpdated","FeedFollowed","ForcePageReload","FollowedTopicsUpdated","MediatedCoachMark","TabNavigation","TabNavigateTo","TopicAction","Msn360","CardActionInit","CardActionPost","InterestsRenderComplete","RenderXFeed","ShowPivotById","ResumeInfopaneAutoRotate","StartMarkSuffix","PerfMarker","endMarkSuffix","initialize","instance","measureStartEnd","startMark","endMark","perfMarkers","perfEntries","perfMarkerDetail","PerfMarkerDetail","processPerfEntry","perfMarker","perfEntry","firstStartTime","IntraArticleComponentPosition","IntraArticleComponentType","getTrack","getMediator","getTrackExtCompleteCanary","trackingResolved","trackingObject","trackExtCompleted","trackEventBuffer","trackImpressionBuffer","trackAppErrorEventBuffer","trackingPromiseCalled","sendTrackingCall","element","destination","headline","trackEvent","sendPartialPageRequest","elem","visibilityCheck","mechanism","topLevelContainerType","trackPartialImpression","sendTrackAppErrorEvent","appError","trackAppErrorEvent","errId","errSource","errMsg","processPendingTrackingCall","eventObj","handleTelemetryCall","handlePartialPageImpressionCall","handleAppErrorEventCall","ActionHandler","actionMap","actionMaps","actionPayloadType","String","ViewsStringResource","article","image","video","gallery","exitFullscreen","fullscreen","nextSlide","previousSlide","publishedSecondAgo","publishedSecondsAgo","publishedMinuteAgo","publishedMinutesAgo","publishedHourAgo","publishedHoursAgo","publishedDayAgo","publishedDaysAgo","gallerySlideError","sharingToolbarLoadFailure","invalidCMSIdErrorFormat","documentDataFetchErrorFormat","intraArticleComponentErrorFormat","gallerySlideCountFormat","gallerySlideCountFullScreenFormat","seeOnProviderSite","socialFeedNotSupported","articleReadMoreText","Telemetry","parentTelemetry","childTelemetry","parentIndex","telemetryName","telemetryType","initTelemetryProps","resultTelemetryProps","createProps","setChildProps","random","rootTelemetryIndex","rootIndex","getNewIndex","ordinalTracker","ordinal","childIndices","childOrdinalCounter","savedProps","componentProps","initializationProps","resetChildProps","ct","f","feedId","h","headlineIndex","y","v","vertical","filteredResult","tags","userFacingText","telemetryIndex","oldProps","newProps","telemetry","0","SubnavTabName","Interests","MyFeed","XFeed","ImageResizeMode","defaultImageWidth","defaultImageHeight","defaultImageQuality","defaultDpi","htmlTagsRegEx","ViewsUtility","imgObj","alt","attribution","caption","getImageUrl","imageServiceUrl","dpi","resizeMode","None","quality","options","focalRegion","opts","LetterBoxing","FocalCropping","BackgroundColor","x","x1","x2","y1","y2","imageCaption","altPrefix","altText","stripHtmlTags","linksCount","telemetryProps","markup","partnerLinksCount","additionalProps","getChildTelemetryItem","Navigation","safeAny","list","dateTime","currentTime","publishTime","timeSpanInSeconds","trunc","timeSpanInMinutes","timeSpanInHours","timeSpanInDays","toLocaleDateString","cmsId","parser","nsParts","sections","charReplaceTable","charRegExp","pair","removeRegExp","dashRegExp","urlTitle","cc","urlData","getFriendlyTitleForUrl","q","input","replaceWith","applyTextTruncationStyles","numLines","display","inViewportPercentage","inViewportTopOffset","inViewportBottomOffset","allowZeroHeight","currentReference","current","bounds","getBoundingClientRect","bottom","TelemetryTypes","ContentTypes","prodAssets","ENV","segments","initializeHybridPublicPath","ExperienceState","ChildExperiencesDeferRenderType","CommonActions","renderExperience","ActionMap","dataConnectorMergeInit","ValidatorSectionName","apptypeValidator","expValidatorMap","getAllValidators","expConfig","size","childExpValidatorMap","expMap","validatorName","childExpValidator","validator","filterConfig","riverGridChildren","childElems","children","childExp","configInfo","childExperienceConfigInfo","experienceType","sectionName","removeFromRiverGridChildren","configIndexHref","parentStore","experienceConnector","experienceComponent","$experienceType","isDataConnector","TelemetryBase","uniqueId","configResult","configPromise","instrumentPromise","getConfig","properties","loaderPromises","bundlePromise","loadExperience","bundleModule","initMeasureEnd","updateExperienceLoadedMilestone","config","ExperienceConnector","ExperienceReducer","app","experienceNamespace","experienceConfigInfo","experienceParentNamespace","experienceStore","configHref","connectorProps","loadConnector","connectComponent","milestoneDataConnector","getActionSender","send","loaded","ConfiglessConnectors","BingImageData","OneServiceContent","TopicData","PageClickTrackerData","DataConnector","childMap","telemetryTags","$experienceGroup","$connectedComponent","$componentInstance","$renderIfOffline","$maxWaitToBatchRenderChildExperiences","$milestoneDataConnector","onExperienceMilestoneTimingUpdate","milestoneType","ExperienceMilestoneEventTypes","domComplete","initialized","rendered","visuallyReady","onAppError","selectComponentState","processConfig","childComponentList","componentInstance","ownProps","stateProps","dispatchProps","mnsDashBoardProps","ShowMnsCreatorDashboard","componentToConnect","onLine","connectMeasureEnd","WrappedComponent","onComponentConnect","Component","lastRenderEndMeasure","mapStateToProps","instrumentFunc","mapDispatchToProps","mergeProps","connectedComponent","pure","experienceInfoList","mergeStartPosition","additionalChildExperiences","ordinalBlockForCurrentColumn","getOrdinalObjectForCurrentBreakpoint","mergeEndPos","childArrangementMetadata","childExpArrangement","positionProps","experienceArrangement","startPosition","insertAt","experienceInfo","initialProps","$connectorProps","isEmpty","Module","onAppErrorCallback","loadDataConnectors","injectedDataConnector","injectedDataConnectors","onLoadChildExperiences","baseExperienceConfig","childrenConfigInfo","composition","ExperienceCompositionTypes","horizontalStack","layout","page","grid","column","childType","ChildrenTypes","peregrineExperience","child","rows","row","columns","itemType","customExperience","customConfig","experience","loadChildrenExperiences","childConnectorProps","childExpsToLoadImmediately","reRenderCallback","readyExperienceToRender","promiseDependency","startProcessingChildExperience","dataConnectors","dataConnectorForCurrentScreenType","loadDataConnector","childConnector","getChildExperienceConnector","addConnectorToChildMap","Failed","childExperienceType","childExperienceInstanceId","context","screenTypeObjList","currentColumnArrangement","getMetadataByScreenWidth","ScreenWidth","OneColumn","TwoColumn","ThreeColumn","FourColumn","Any","screenWidth","obj","loader","getConnectedExperience","getChildExperienceConnectorProps","getNewComponentInstance","removeCachedConfig","milestoneDependencyToLoadChildExp","shouldResolve","addTimeout","deferralType","CustomEventBasedDeferral","Unknown","resolveDependency","loadAndRenderExperience","childExpInfo","delayLoaded","milestoneDependencyToRenderChildExp","ReadyToRender","reRender","childExperiencesRenderType","batch","reRenderExperience","dependency","pending","timer","PrimeIntegrationConstants","AnonCookieName","userActionErrorCoachMarkId","Mediator","getActiveTabValue","activeTabValue","navigation","activeTab","tabNameToTabId","registerForTabChangeEvent","shouldCallCallbackImmediately","sendActiveTabToCallback","tab","_perfMarker","tabIdToTabName","sub","registerContentActionsUpdatedEvent","registerCardActionEnableEvent","initData","registerCardActionPostEvent","postData","registerForFollowButtonClickEvent","followButtonData","topicId","isFollowed","registerForInterestsRenderCompleteEvent","publishEventForPrime","pub","renderUserActionErrorCoachmark","refElement","hideCoachMark","coachMarkId","renderCacheObject","batchCSS","batchCss","styles","dataset","innerHTML","scrapeDom","includeNewsFeed","root","rivers","getElementsByClassName","river","outerHTML","getStateFromRenderCache","renderCache","cacheExpirationTimestamp","parsedCacheExpirationTimestamp","renderCacheStorage","dom","batch_css","getRenderCache","reduxStoreStringifyReviver","dataType","sendSinglePageViewBeacon","loggingService","maxRetries","baseRetryDelayInMs","maxRetryDelayInMs","factor","minOffsetInMs","maxOffsetInMs","loggedExceptionManager","LoggedExceptionManager","logInvalidParams","defaultMaxRetries","defaultBaseRetryDelayInMs","maxAllowedRetryDelayInMs","defaultFactor","defaultMinOffsetInMs","defaultMaxOffsetInMs","minTimeout","maxTimeout","serviceCall","requestInfo","activity","tryRequest","maxAllowedRetries","fatal","currentRetry","timeoutServiceRequest","fractionDigit","offset","parseFloat","toFixed","half","plusOrMinus","delayWithOffset","min","pow","warnCallback","errorCallback","timeoutId","instrumentationService","exponentialBackoffRetry","retryCount","sendRequest","activityName","getInstrumentationService","activityLoggingService","createActivity","getExponentialBackoffRetry","executeRequest","endActivity","activityService","ActivityLoggingService","BrowserConsoleAppender","LogLevel","Activity","InstrumentationService","getLoggingService","FastBreakpointManager","callbackMap","refreshBreakpoints","defaultBreakpoint","breakpoints","indexToStandardConverter","currentBreakpoint","fastBreakpointManager","isArray","pop","breakpoint","update","managerCallback","subscribe","unsubscribe","feedServiceUrl","getServiceUrl","initializationLogs","initializeServiceRequest","EnterpriseServiceUrlBase","ServiceUrlBase","getFeedServiceUrl","initializeFeedServiceRequest","FeedServiceUrlBase","getServiceUrlForSubpath","getFeedServiceUrlForSubpath","authEnabled","TabsHelper","tabId","tabName","DynamicBundles","dynamicBundles","bundle","registerExperience","es6Import","peregrineFlightPrefix","getPeregrineFlights","cleanedUpFlights","lowercaseItem","SERVER_CACHE_TTL","SERVER_CACHE_CONFIG_STALENESS_TIMEOUT","currentTargetScope","CurrentRequestTargetScope","configMap","promiseMap","stalenessCheckTimestamp","initializeIndexedDb","memoize","_initializeIndexedDb","populateConfigMapFromIndexedDbAsync","_populateConfigMapFromIndexedDbAsync","initializeCaching","idb","cdnConfigBaseUrl","ConfigRootUrl","EnvironmentConfigUrl","ConfigServiceBaseUrl","resolverErrors","configTimings","useWebWorkerToCache","indexedDb","IndexedDb","useIndexedDb","enableIndexedDbInMainResolver","DisableCachingConfigs","isCachingAllowed","useServerCache","ServerCache","useConfigService","scopeWithPeregrineFlights","configServiceParameters","IsMultiConfigRetrievalEnabled","CacheBustingIdentifier","getConfigRetrievalMaxDepth","containsDevOnlyQueryParameters","generateKey","configs","mergeWith","customizer","configIndex","configPaths","experienceRef","targetScopeMatched","overrideConfig","targetScope","audienceModeMatched","browserTypeMatched","deviceTypeMatched","experimentMatched","marketMatched","osMatched","pageTypeMatched","platformMatched","browserType","version","isString","experimentId","lhs","rhs","localeCompare","sensitivity","targetLocale","currentLocale","stringsEqualCaseInsensitive","srcValue","objValue","clear","cache","overrideEnv","relativeUrl","addConfigToConfigMap","typeVersion","_name","cacheKey","getCacheKey","startGetConfig","configFromMemory","addConfigTiming","existingPromise","processed","configEndMeasure","configSource","serializedConfig","configFromServerCache","cacheFetchDuration","isServerCacheConfigStale","storageTimestamp","del","logPrefix","networkReadPromise","getConfigFromNetwork","networkConfig","readPromises","configFromMemoryAfterRace","mergedConfigsMap","configServiceRelativeUrl","removeCmsPathFromRelativeUrl","crsResponse","downloadFile","rootConfigIndexId","crsMergedConfig","values","configIndexKey","crsConfig","cdnConfig","downloadMergeConfig","areConfigsEqual","removeSubstringKeys","experienceIndex","resolveConfigIndex","configObjects","downloadExperienceConfig","mergeConfig","baseConfigUrl","hrefs","promiseArray","fetch","toString","ok","statusText","json","EnableConfigService","FeatureFlags","crsMaxDepth","segment","wwResponse","purgeRenderCacheUponConfigChanges","clearConfigCache","clearObjects","getAllConfigTimingsOverride","allConfigsCacheDuration","allConfigsNetworkDuration","configTiming","networkFetchDuration","IsDebug","round","configFetchTimings","cacheSource","startBulkConfig","cachedConfigs","_idbConfigReadPromise","_idbConfigLookup","getObject","populateConfigMapFromCachedConfigs","_idbConfigOpenPromise","unusableCount","cachedConfig","isConfigStale","resolver","getConfigTimings","getResolverErrors","refreshConfigCache","overrideCurrentRequestTargetScope","overrideCurrentRequestEnvironment","clearInternalState","getConfigServiceParameters","setConfigTimingsObject","searchObj","IDBObjectStore","getAll","idbPromise","req","withIdbStore","storeCallback","isGetAllAllowed","returnArray","openCursor","onsuccess","cursor","continue","put","idbVersion","idbStoreName","dbName","preInitializedIdbPromise","storeName","endOpen","openreq","open","onupgradeneeded","createObjectStore","operationName","db","endOperation","transaction","oncomplete","onabort","objectStore","serverCache","reset","itemCount","_fullNamespace","selectState","_subspace","_perfTimeline","addSubReducerForConnector","_configHref","getState","globalConnectors","globalConnector","namespaceParts","connectorType","DeferralEventType","CustomDeferralEventTypes","ExperienceDeferralEventTypes","defaultInstanceKeyName","defaultTimeValue","experienceDeferralDependencyMap","isExperienceDependencyResolved","experienceDependency","deferralEventType","deferralIdentifier","currentState","getMilestoneDataConnector","MilestoneData","getDefaultExperienceInstance","milestones","perExperienceMilestones","perInstanceMilestones","getExperienceLoadDelegate","deferralEventReady","loadAfter","eventType","aboveTheFoldVisuallyReady","isAboveTheFoldVisuallyReady","belowTheFoldTransitionStart","isBelowTheFoldTransitionStarted","getDeferralLoadEventReadyState","shouldLoad","getDeferralEventMetadata","waitForAboveTheFoldVisuallyReadyAsync","registerObserver","getExperienceRenderDelegate","renderAfter","getDeferralRenderEventReadyState","shouldRender","Boolean","deferralInfo","StandardEventBasedDeferral","PerfTracker","visuallyReadyTracker","initializedTracker","domCompleteTracker","startInitializeMilestone","startVisuallyReadyMilestone","startDomCompleteMilestone","endDomCompleteMilestone","prevProps","prevState","snapshot","endInitializeMilestone","shouldMarkTelemetryTtvr","endVisuallyReadyMilestone","setStart","getStart","getEnd","setEnd","timeToFunctional","timeToVisuallyReady","timeToVideoStart","remainingMarkers","remainingTtvrMarkers","resolveTtvrCallback","perfMarkerResolveCallback","resolveTtvsCallback","markers","ttfPrefix","ttvrPrefix","ttvsPrefix","markTtvr","markTimeNA","time","setMark","markTtvrRaf","requestAnimationFrame","prefix","markerFullName","existingMarker","getEntriesByName","getTtvrMarkers","getMarkers","getMarkersWithType","markerPrefix","SocialMediaProviderConfig","SocialMedia","SocialMediaTarget","apiUrl","FacebookEmbed","InstagramEmbed","TwitterEmbed","SocialMediaDefaultConfig","Email","backgroundColor","color","Mail","label","_self","Facebook","_blank","Line","LinkedIn","Skype","Twitter","WhatsApp","anchor","autoFlipX","autoFocus","enable","left","onDismiss","staticPosition","zIndex","tabEventHandler","keyCode","popOverRef","contains","activeElement","tabbable","shiftKey","focus","preventDefault","determinePosition","scrollY","scrollX","createRef","setState","zIndexStyle","direction","unhandledProps","onKeyDown","tabIndex","ref","popOver","getPlacementStyle","popOverPlaceholder","createPortal","pageDirection","position","windowWidth","documentHeight","documentElement","offsetHeight","displayOnLeft","right","displayOnRight","displayOnPrioritySide","displayOnNonPrioritySide","rtl","canFitPrioritySide","canFitNonPrioritySide","PopOverStyles","Flyout","outline","visibility","opacity","transform","ZIndex","ImageServiceConfig","settingButton","border","background","padding","outlineWidth","settingButtonIcon","contextMenuItem","margin","contextMenuItem_contentRegion","contextMenuItem_image","contextMenu","menuItems","enabled","buttonLabel","positionOffset","telemetryTag","handleUnfocus","node","containerRef","buttonContainerContainsNode","menuRef","parentNode","menuPopoverContainsNode","closeMenu","menuOpened","buttonRef","addEventListener","removeEventListener","menuContainer","onClick","onSettingClick","renderPopOver","dropDownLocation","isNil","enableAutoFocus","renderContextMenu","itemProps","attr","onInvoke","onMenuItemClick","onSelect","text","onSelectCallback","posOffset","offsetX","offsetY","ButtonStyle","button__justified","iconContainer","iconImage","iconLabel","socialMedia","contentUrl","contentTitle","hideLabel","socialMediaItemConfigOverride","onClickNewWindow","shareUrl","newWindowOptions","newWindowTelemetryCall","openNewWindow","itemConfig","getSocialMediaShareUrl","targetRelatedAtributes","newWindow","attributes","appearance","justified","jssStyleSheet","ShallowCompare","a","b","ShareDialogColors","setStyleByZIndex","overrides","dialog_modalOverlay","dialog_contentRegion","StringResource","dialogStrings","dialogButtonClose","dialogTitle","copyButton","copiedButton","copyButtonAriaLabel","copiedButtonAriaLabel","Dialog","dialog","Above","linkCopiedDisplayDuration","fallbackStyles","backgroundStyle","closeButton","closeIcon","copyLinkButton","copyLinkInput","dialogContainer","header","headerText","semibold","iconListContainer","iconListItem","float","inputContainer","baseDialogProps","closeButtonTelemetryTags","copyButtonAttributes","copyButtonTelemetryProps","copyButtonTelemetryTags","copyLinkOcid","onClose","socialMediaConfigOverride","socialMediaItems","shareIconTelemetryProps","shareIconTelemetryTags","baseDialogStyleOverride","inputRef","onCopyLinkToClipboard","isLinkCopied","execCommand","setSocialMediaItemsConfig","coerceDialogProps","_7","tag","h3","Close","renderSocialIconsList","renderCopyLink","buttonText","copyTelemetryTag","readOnly","socialMediaIcons","renderSocialIcon","socialMediaItem","media","mediaKey","iconTelemetryTags","socialMediaItemsConfig","keyLower","visible","modal","contentHeight","contentWidth","anchorRef","headlineTitle","provider","nextProps","articleCard","renderContent","content","articleCard_content","renderImage","articleCard_textWrapper","renderTitle","renderProvider","articleCard_imageWrapper","articleCard_image","articleCard_imageOverlay","articleCard_headline","articleCard_headlineText","articleCard_headlineMask","providerImage","articleCard_providerImage","articleCard_provider","articleCard_providerTitle","SharedDocumentType","SharingHelper","sharingInfo","appId","getAppId","getSharingUrlBase","sharingUrl","shortUrlPathFormat","documentType","documentId","AppKeys","Base36AppIdString","articleUrl","currentBaseUrl","SharingProductionHosts","SharingBaseUrlDefault","overrideShareUrl","socialMediaItemConfig","appendQueryStringFormat","Format","refererUrl","finalOptions","entries","BreakpointIndexToPx","ToolbarBreakpoints","TelemetryConstants","PlaceHolderId","LikeDislikeActionKey","SelectPropKey","Status","ButtonType","ContentActionsToolbarActions","initializeToolbar","ContentStatuReady","documentDataReady","likeContent","unlikeContent","dislikeContent","undislikeContent","sharingToolbarError","ViewportUpdate","moreOptionsIconColors","likeDislikeIconBackroundColor","moreOptionsMenuDefaultOffsetPos","OptionItemLike","like","Like","OptionItemDislike","dislike","Disliked","OptionItemUndoLike","undoliked","OptionItemUndoDislike","undodisliked","Dislike","inspect","localizedStrings","sharingToolbar","sharingButtons","contentStatus","status","sharingError","sharingShortUrl","documentData","articleTitle","articleImageUrl","providerName","providerLogoUrl","buttonItem","newButtonItem","cloneDeep","buttonType","buttonData","ShareDialog","shareDialogProps","shareDialogTitleText","shareDialogCopyButtonText","shareDialogCopyButtonAriaLabelText","shareDialogCopiedButtonText","shareDialogCopiedButtonAriaLabelText","dialogArticleCardProps","articleId","shareDialogButtonAriaLabelText","LikeDislike","likeDislikeButtonAriaLabelText","MoreOptions","moreOptionsUnlikeText","moreOptionsUnlikeAriaLabelText","moreOptionsDislikeText","moreOptionsDislikeAriaLabelText","DisLike","moreOptionsUndislikeText","moreOptionsUndislikeAriaLabelText","moreOptionsLikeText","moreOptionsLikeAriaLabelText","moreOptionsButtonAriaLabelText","offsetPos","missingChildren","fetchImpl","contentActionsServiceEndpoint","contentPreviewApiEndpoint","targetId","GetContentStatusRequest","isLike","actionType","isDislike","contentPreviewData","GetContentPreviewData","TranslateContentPreviewDocumentData","PostContentActionRequest","DeleteContentActionRequest","requestParams","credentials","contentStatusData","ContentServiceUrlBase","deleteQueryParam","deleteResponse","targetType","postResponse","articleDataResponse","articleImageId","providerLogoId","sharingToolbarTelemetryProps","button","buttonTelemetryName","mediaType","currentTarget","mediaTelemetryProps","Share","copyLinkTelemetryName","closeButtonTelemetryProps","closeDialogTelemetryName","mediaItem","mediaItemOverride","shareDialogTelemetryProps","shareDialogTelemetryName","Interaction","articleTelemetryTags","shareArticleTelemetryName","Unlike","Undislike","ComponentConnector","inspectorArgs","contentActionsToolbarProps","inspectorResponse","callbacks","BuildLikeDislikeCallbacks","InjectCallbacksToMoreOptionsMenu","InjectTelemetry","onDislike","onLike","rootTelemetryTags","sharingToolbarTelemetryTags","contentId","isRSThree","CMS","actionServiceClient","generateTelemetryTags","getContentStatus","getDocumentData","initializeBreakpointTracker","GetPreferenceInitialState","GetDocumentData","shortUrlBuilder","moreOptionsButton","socialToolbarTelemetryName","moreOptionsTelemetryTags","UndoLike","UndoDislike","ToolbarPosition","handleAction","breakpointIndex","isRSThreeDevice","getToolbarPosition","Breakpoint3_2","Breakpoint3_3","horizontal","SharingToolbarStyles","icon_none","icon_like","icon_dislike","iconListHorizontal","iconListVertical","shareDialog","moreOptions","contextMenuStyles","e11","ArticleImageDimension","Scale","flex","articleCard_noImage","viewsImageData","getResizedImageUrl","ArticleCard","coerceTitleProps","coerceProviderProps","coercedProps","_6","coercedProviderNameProps","_8","h5","onShareDialogOpen","shareDialogOpened","onShareDialogClose","getPositioningClassName","renderSharingButtons","renderShareDialog","managedClass","buttonId","listItem","renderSocialMediaIcon","renderShareDialogIcon","renderLikeDislikeIcon","renderMoreOptionsIcon","shareDialogItem","articleCardStylesheet","LikedText","LikeText","DislikeText","iconClassName","BaseExperience","customField","firstRenderCompleted","contentActionsToolbar","componentDidUpdate","shouldFlip","flipToolbar","stack","contentActionsToolbar_horizontal","contentActionsToolbar_vertical","currentHostId","hostElem","prevHostId","newHostId","prevHostElem","newHostElem","childNodes","defaultProps","mockDocumentId","start","appTelemetry","createRootProps","RootTelemetryId","setupContentActionsInitialState","cmsDocumentId","documentid","isrsthree","verticalkey","categorykey","connectContentActionsComponent","contentActionsToolbarConfig","contentActionsExperience","renderRootElement","contentActionsConfig","experienceConfig"],"mappings":"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uB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,uBAA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C,EAAOD,QAAU,IAA0B,mB,gBCA3CC,EAAOD,QAAU,IAA0B,wB,gBCA3CC,EAAOD,QAAU,IAA0B,a,gBCA3CC,EAAOD,QAAU,IAA0B,e,gBCA3CC,EAAOD,QAAU,IAA0B,mB,gBCA3CC,EAAOD,QAAU,IAA0B,kB,gBCA3CC,EAAOD,QAAU,IAA0B,uB,gBCA3CC,EAAOD,QAAU,IAA0B,a,gBCA3CC,EAAOD,QAAU,IAA0B,c,gBCA3CC,EAAOD,QAAU,IAA0B,mB,gBCA3CC,EAAOD,QAAU,IAA0B,Y,gBCA3CC,EAAOD,QAAU,IAA0B,qB,gBCA3CC,EAAOD,QAAU,IAA0B,e,gBCA3CC,EAAOD,QAAU,IAA0B,c,gBCA3CC,EAAOD,QAAU,IAA0B,e,gBCA3CC,EAAOD,QAAU,IAA0B,mB,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,qB,gBCA3CC,EAAOD,QAAU,IAA0B,oB,gBCA3CC,EAAOD,QAAU,IAA0B,Y,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,Y,gBCA3CC,EAAOD,QAAU,IAA0B,c,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,qB,gBCA3CC,EAAOD,QAAU,IAA0B,a,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,oB,gBCA3CC,EAAOD,QAAU,IAA0B,yB,gBCA3CC,EAAOD,QAAU,IAA0B,W,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,c,gBCA3CC,EAAOD,QAAU,IAA0B,kB,gBCA3CC,EAAOD,QAAU,IAA0B,Y,gBCA3CC,EAAOD,QAAU,IAA0B,oB,gBCA3CC,EAAOD,QAAU,IAA0B,yB,gBCA3CC,EAAOD,QAAU,IAA0B,yB,gBCA3CC,EAAOD,QAAU,IAA0B,wB,gBCA3CC,EAAOD,QAAU,IAA0B,mB,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,e,gBCA3CC,EAAOD,QAAU,IAA0B,oB,gBCA3CC,EAAOD,QAAU,IAA0B,iB,gBCA3CC,EAAOD,QAAU,IAA0B,sB,gBCA3CC,EAAOD,QAAU,IAA0B,iB,gBCA3CC,EAAOD,QAAU,IAA0B,sB,gBCA3CC,EAAOD,QAAU,IAA0B,iB,gBCA3CC,EAAOD,QAAU,IAA0B,sB,gBCA3CC,EAAOD,QAAU,IAA0B,Y,gBCA3CC,EAAOD,QAAU,IAA0B,iB,gBCA3CC,EAAOD,QAAU,IAA0B,a,gBCA3CC,EAAOD,QAAU,IAA0B,mB,gBCA3CC,EAAOD,QAAU,IAA0B,+B,gBCA3CC,EAAOD,QAAU,IAA0B,gC,gBCA3CC,EAAOD,QAAU,IAA0B,kB,gBCA3CC,EAAOD,QAAU,IAA0B,iB,gBCA3CC,EAAOD,QAAU,IAA0B,sB,gBCA3CC,EAAOD,QAAU,IAA0B,iB,gBCA3CC,EAAOD,QAAU,IAA0B,sB,gBCA3CC,EAAOD,QAAU,IAA0B,Y,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,a,gBCA3CC,EAAOD,QAAU,IAA0B,iB,gBCA3CC,EAAOD,QAAU,IAA0B,Y,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,qB,gBCA3CC,EAAOD,QAAU,IAA0B,oB,gBCA3CC,EAAOD,QAAU,IAA0B,Y,gBCA3CC,EAAOD,QAAU,IAA0B,iB,gBCA3CC,EAAOD,QAAU,IAA0B,wB,gBCA3CC,EAAOD,QAAU,IAA0B,e,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,qB,gBCA3CC,EAAOD,QAAU,IAA0B,yB,gBCA3CC,EAAOD,QAAU,IAA0B,4B,gBCA3CC,EAAOD,QAAU,IAA0B,4B,gBCA3CC,EAAOD,QAAU,IAA0B,oB,gBCA3CC,EAAOD,QAAU,IAA0B,yB,gBCA3CC,EAAOD,QAAU,IAA0B,a,gBCA3CC,EAAOD,QAAU,IAA0B,iB,gBCA3CC,EAAOD,QAAU,IAA0B,uB,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,e,gBCA3CC,EAAOD,QAAU,IAA0B,c,gBCA3CC,EAAOD,QAAU,IAA0B,e,gBCA3CC,EAAOD,QAAU,IAA0B,uB,gBCA3CC,EAAOD,QAAU,IAA0B,4B,gBCA3CC,EAAOD,QAAU,IAA0B,yB,gBCA3CC,EAAOD,QAAU,IAA0B,8B,gBCA3CC,EAAOD,QAAU,IAA0B,W,gBCA3CC,EAAOD,QAAU,IAA0B,c,gBCA3CC,EAAOD,QAAU,IAA0B,W,gBCA3CC,EAAOD,QAAU,IAA0B,kB,gBCA3CC,EAAOD,QAAU,IAA0B,Y,gBCA3CC,EAAOD,QAAU,IAA0B,sB,gBCA3CC,EAAOD,QAAU,IAA0B,2B,gBCA3CC,EAAOD,QAAU,IAA0B,wB,gBCA3CC,EAAOD,QAAU,IAA0B,6B,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,0B,gBCA3CC,EAAOD,QAAU,IAA0B,+B,gBCA3CC,EAAOD,QAAU,IAA0B,4B,gBCA3CC,EAAOD,QAAU,IAA0B,iC,gBCA3CC,EAAOD,QAAU,IAA0B,qB,gBCA3CC,EAAOD,QAAU,IAA0B,e,gBCA3CC,EAAOD,QAAU,IAA0B,c,gBCA3CC,EAAOD,QAAU,IAA0B,Y,gBCA3CC,EAAOD,QAAU,IAA0B,a,gBCA3CC,EAAOD,QAAU,IAA0B,c,gBCA3CC,EAAOD,QAAU,IAA0B,a,gBCA3CC,EAAOD,QAAU,IAA0B,kB,gBCA3CC,EAAOD,QAAU,IAA0B,kB,gBCA3CC,EAAOD,QAAU,IAA0B,a,gBCA3CC,EAAOD,QAAU,IAA0B,mB,gBCA3CC,EAAOD,QAAU,IAA0B,sB,gBCA3CC,EAAOD,QAAU,IAA0B,2B,gBCA3CC,EAAOD,QAAU,IAA0B,wB,gBCA3CC,EAAOD,QAAU,IAA0B,6B,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,qB,gBCA3CC,EAAOD,QAAU,IAA0B,Y,gBCA3CC,EAAOD,QAAU,IAA0B,e,gBCA3CC,EAAOD,QAAU,IAA0B,a,gBCA3CC,EAAOD,QAAU,IAA0B,qB,gBCA3CC,EAAOD,QAAU,IAA0B,qB,gBCA3CC,EAAOD,QAAU,IAA0B,0B,gBCA3CC,EAAOD,QAAU,IAA0B,gB,gBCA3CC,EAAOD,QAAU,IAA0B,e,gBCA3CC,EAAOD,QAAU,IAA0B,oB,gBCA3CC,EAAOD,QAAU,IAA0B,mB,gBCA3CC,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","file":"content-actions-toolbar.b2ff00108fcfe9e94fd6.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t14: 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// script path function\n \tfunction jsonpScriptSrc(chunkId) {\n \t\treturn __webpack_require__.p + \"\" + ({\"85\":\"icon-assets-AdChoices\",\"86\":\"icon-assets-BingCardDefaultHotelImage\",\"87\":\"icon-assets-BingHotelSeePrice\",\"88\":\"icon-assets-BingLogo\",\"89\":\"icon-assets-BingRatingDarkLightStar\",\"90\":\"icon-assets-BingRatingDarkStar\",\"91\":\"icon-assets-BingRatingLightStar\",\"92\":\"icon-assets-BlowingHail\",\"93\":\"icon-assets-BlowingHailWhite\",\"94\":\"icon-assets-BlowingSnow\",\"95\":\"icon-assets-BlowingSnowWhite\",\"96\":\"icon-assets-Check\",\"97\":\"icon-assets-Chevron\",\"98\":\"icon-assets-CircleClose\",\"99\":\"icon-assets-ClearNight\",\"100\":\"icon-assets-ClearNightWhite\",\"101\":\"icon-assets-Close\",\"102\":\"icon-assets-Cloudy\",\"103\":\"icon-assets-CloudyWhite\",\"104\":\"icon-assets-Copy\",\"105\":\"icon-assets-DarkModeHotel\",\"106\":\"icon-assets-DayTime\",\"107\":\"icon-assets-Delete\",\"108\":\"icon-assets-Dislike\",\"109\":\"icon-assets-DislikeText\",\"110\":\"icon-assets-Disliked\",\"111\":\"icon-assets-DislikedLight\",\"112\":\"icon-assets-DislikedText\",\"113\":\"icon-assets-Docx\",\"114\":\"icon-assets-DoubleTap\",\"115\":\"icon-assets-Download\",\"116\":\"icon-assets-Edit\",\"117\":\"icon-assets-Edited\",\"118\":\"icon-assets-Ellipses\",\"119\":\"icon-assets-EllipsesLight\",\"120\":\"icon-assets-EmptyMruDark\",\"121\":\"icon-assets-EmptyMruLight\",\"122\":\"icon-assets-EmptyPinnedDark\",\"123\":\"icon-assets-EmptyPinnedLight\",\"124\":\"icon-assets-EmptySharedDark\",\"125\":\"icon-assets-EmptySharedLight\",\"126\":\"icon-assets-Excel\",\"127\":\"icon-assets-Facebook\",\"128\":\"icon-assets-FacebookText\",\"129\":\"icon-assets-FacebookTextBlack\",\"130\":\"icon-assets-Fog\",\"131\":\"icon-assets-FogWhite\",\"132\":\"icon-assets-Folder\",\"133\":\"icon-assets-FolderOpen\",\"134\":\"icon-assets-Form\",\"135\":\"icon-assets-FreezingRain\",\"136\":\"icon-assets-FreezingRainWhite\",\"137\":\"icon-assets-GalleryFullscreen\",\"138\":\"icon-assets-GalleryMediaIcon\",\"139\":\"icon-assets-GenericFile\",\"140\":\"icon-assets-GridView\",\"141\":\"icon-assets-HailDay\",\"142\":\"icon-assets-HailDayWhite\",\"143\":\"icon-assets-HailNight\",\"144\":\"icon-assets-HailNightWhite\",\"145\":\"icon-assets-HazeSmoke\",\"146\":\"icon-assets-HazeSmokeWhite\",\"147\":\"icon-assets-HeavySnow\",\"148\":\"icon-assets-HeavySnowWhite\",\"149\":\"icon-assets-Hide\",\"150\":\"icon-assets-HideStory\",\"151\":\"icon-assets-Hotel\",\"152\":\"icon-assets-Information\",\"153\":\"icon-assets-InteractionRequiredDark\",\"154\":\"icon-assets-InteractionRequiredLight\",\"155\":\"icon-assets-Interested\",\"156\":\"icon-assets-LightRain\",\"157\":\"icon-assets-LightRainWhite\",\"158\":\"icon-assets-LightSnow\",\"159\":\"icon-assets-LightSnowWhite\",\"160\":\"icon-assets-Like\",\"161\":\"icon-assets-LikeText\",\"162\":\"icon-assets-Liked\",\"163\":\"icon-assets-LikedText\",\"164\":\"icon-assets-Line\",\"165\":\"icon-assets-LinkedIn\",\"166\":\"icon-assets-LinkedInBlack\",\"167\":\"icon-assets-LinkedInText\",\"168\":\"icon-assets-Mail\",\"169\":\"icon-assets-MailBlack\",\"170\":\"icon-assets-ManagedBriefcase\",\"171\":\"icon-assets-Message\",\"172\":\"icon-assets-Messages\",\"173\":\"icon-assets-MicrosoftNews\",\"174\":\"icon-assets-MicrosoftNews_FR\",\"175\":\"icon-assets-MicrosoftNews_ZH\",\"176\":\"icon-assets-ModerateRain\",\"177\":\"icon-assets-ModerateRainWhite\",\"178\":\"icon-assets-Movie\",\"179\":\"icon-assets-NightTime\",\"180\":\"icon-assets-Notification-Five-Plus-Sign\",\"181\":\"icon-assets-OfficeFormsLogo\",\"182\":\"icon-assets-OneDrive\",\"183\":\"icon-assets-OneNote\",\"184\":\"icon-assets-Onetoc\",\"185\":\"icon-assets-Outlook\",\"186\":\"icon-assets-PartlyCloudyDay\",\"187\":\"icon-assets-PartlyCloudyDayWhite\",\"188\":\"icon-assets-PartlyCloudyNight\",\"189\":\"icon-assets-PartlyCloudyNightWhite\",\"190\":\"icon-assets-Pdf\",\"191\":\"icon-assets-People\",\"192\":\"icon-assets-Pin\",\"193\":\"icon-assets-PowerPoint\",\"194\":\"icon-assets-Pptx\",\"195\":\"icon-assets-RainShowersDay\",\"196\":\"icon-assets-RainShowersDayWhite\",\"197\":\"icon-assets-RainShowersNight\",\"198\":\"icon-assets-RainShowersNightWhite\",\"199\":\"icon-assets-RainSnow\",\"200\":\"icon-assets-RainSnowShowersDay\",\"201\":\"icon-assets-RainSnowShowersDayWhite\",\"202\":\"icon-assets-RainSnowShowersNight\",\"203\":\"icon-assets-RainSnowShowersNightWhite\",\"204\":\"icon-assets-RainSnowWhite\",\"205\":\"icon-assets-Refresh\",\"206\":\"icon-assets-Remove\",\"207\":\"icon-assets-Save\",\"208\":\"icon-assets-Saved\",\"209\":\"icon-assets-Search\",\"210\":\"icon-assets-Share\",\"211\":\"icon-assets-ShareLight\",\"212\":\"icon-assets-Sharepoint\",\"213\":\"icon-assets-Skype\",\"214\":\"icon-assets-SkypeOffice\",\"215\":\"icon-assets-SnowShowersDay\",\"216\":\"icon-assets-SnowShowersDayWhite\",\"217\":\"icon-assets-SnowShowersNight\",\"218\":\"icon-assets-SnowShowersNightWhite\",\"219\":\"icon-assets-SunnyDay\",\"220\":\"icon-assets-SunnyDayWhite\",\"221\":\"icon-assets-Sway\",\"222\":\"icon-assets-SwayApp\",\"223\":\"icon-assets-Teams\",\"224\":\"icon-assets-ThumbnailView\",\"225\":\"icon-assets-Thunderstorms\",\"226\":\"icon-assets-ThunderstormsWhite\",\"227\":\"icon-assets-Trending\",\"228\":\"icon-assets-Twitter\",\"229\":\"icon-assets-TwitterBlack\",\"230\":\"icon-assets-TwitterText\",\"231\":\"icon-assets-Unpin\",\"232\":\"icon-assets-VerticalSeparator\",\"233\":\"icon-assets-VideoMediaIcon\",\"234\":\"icon-assets-VideoPlay\",\"235\":\"icon-assets-Visio\",\"236\":\"icon-assets-Vsdx\",\"237\":\"icon-assets-WeatherAlert\",\"238\":\"icon-assets-WhatsApp\",\"239\":\"icon-assets-WhatsAppBlack\",\"240\":\"icon-assets-Windy\",\"241\":\"icon-assets-WindyWhite\",\"242\":\"icon-assets-Word\",\"243\":\"icon-assets-World\",\"244\":\"icon-assets-Xlsx\",\"245\":\"icon-assets-Yammer\"}[chunkId]||chunkId) + \".\" + {\"85\":\"025175e17a78837ddef2\",\"86\":\"1210803838b494b4935a\",\"87\":\"9f6d4020715879c145e9\",\"88\":\"65895b55caf149393a28\",\"89\":\"d6ee01f4c109ca57d1fe\",\"90\":\"ed06f357714849f6ef34\",\"91\":\"a52c52ead6bee92967b4\",\"92\":\"36a16392b8c8bad35c06\",\"93\":\"c10dee9e624abe08f9f6\",\"94\":\"01f9dceb8ce0ead11fac\",\"95\":\"7973cae6f36e2d430756\",\"96\":\"c418047baa4911cc22f9\",\"97\":\"a74a98d371271121f844\",\"98\":\"d4b70d1b5b26fcc0836c\",\"99\":\"f9a9c4288b32fe3772ff\",\"100\":\"35aeb487a36c3bbf8229\",\"101\":\"f2ce423a6b547e1de637\",\"102\":\"64a56c39aaf1af9dea29\",\"103\":\"f2fac49875f0a112e75d\",\"104\":\"6f07d646b2d1f530e915\",\"105\":\"1baffebbd74e3fb2aef3\",\"106\":\"5141d59985a550851cef\",\"107\":\"13d313df187c56340d52\",\"108\":\"35aa04e78918ea98eb7a\",\"109\":\"34e5c6e375599a4d082b\",\"110\":\"9ed7a456e88c913117ba\",\"111\":\"9d0fa9087dd82f03681f\",\"112\":\"17d0e574ae64d491c89e\",\"113\":\"cd1270ac9eadaaa53e4a\",\"114\":\"fa8b7ef8b52f7c84c285\",\"115\":\"17606a329e13a1f57fc4\",\"116\":\"86650009d4ded38889a1\",\"117\":\"d95de38e710668b45ec3\",\"118\":\"4c86bc59ee29f52e2b23\",\"119\":\"1ae844ca5313a6bcd156\",\"120\":\"103d0bc2dcf96e524b2f\",\"121\":\"522b8ceaba1ddbfd4887\",\"122\":\"9b386d61db585fd2fc8e\",\"123\":\"33f9cb24d9facf60e080\",\"124\":\"2e9b6a696d88c554d7c3\",\"125\":\"92dfac12ce7b43582543\",\"126\":\"1eb89d7c751a1be55e62\",\"127\":\"b02abfd97b9a3e4777cf\",\"128\":\"b5f5a857ff2a4627a733\",\"129\":\"9748edb474e06b14ac3c\",\"130\":\"bcc8d9e05352fcd32b8e\",\"131\":\"dcd207fca65beba893bd\",\"132\":\"f2d22414408fba78babc\",\"133\":\"2b34240619a7127ef9b5\",\"134\":\"ef5fa2e92209332fcad8\",\"135\":\"85ba705a4c2ed22f6962\",\"136\":\"777088997195b2582fcd\",\"137\":\"1f1e4d09b36924ea2f70\",\"138\":\"2ce69ac8a3662f39fd6c\",\"139\":\"c0d065182fc7903cfaae\",\"140\":\"2a34944de1cb6722cb93\",\"141\":\"34b7f597a09148619366\",\"142\":\"6d61e5ca17da22ad07bc\",\"143\":\"861f29f86a4bd657500a\",\"144\":\"26725144fb4bffe7d240\",\"145\":\"0d71012aff0c711685b2\",\"146\":\"1395e367ce4504b7dcb7\",\"147\":\"b972b87d0e0c7b55fc65\",\"148\":\"4b510835d74003938ef5\",\"149\":\"def2c2d8913eb6a47859\",\"150\":\"fec90d66178577cd885a\",\"151\":\"b18f67c998128256e92d\",\"152\":\"fb2f1cc229af2a2890ac\",\"153\":\"cd046096fc13270ac60d\",\"154\":\"32b83ef359ea5244cfae\",\"155\":\"a7a6cd20ed1c7215e561\",\"156\":\"f6442e299a2a4a0bf8ef\",\"157\":\"829ce8b89da48a0dc0c8\",\"158\":\"b31ed56214825dac5e3e\",\"159\":\"114626738281fe81bb4c\",\"160\":\"9efdbe3ae078929968a8\",\"161\":\"9511934da06d33f2795e\",\"162\":\"4019f46edef954308ce4\",\"163\":\"0b3dc2623bbfabcea3b5\",\"164\":\"bae2ed9e2336803e9c93\",\"165\":\"f537b0de54e82dcf82c1\",\"166\":\"9a7b99184ffaa581f5c3\",\"167\":\"f873694c963a90b6952d\",\"168\":\"54a2e9716e48f961a4bc\",\"169\":\"0743d402caf885d96b1f\",\"170\":\"05254068230a89b226a2\",\"171\":\"8ddb0577b233c3ffa82b\",\"172\":\"91fac76a9ef7db3e0825\",\"173\":\"1d016ba8570003433182\",\"174\":\"a8fbde78468f72d313a9\",\"175\":\"427f1954fae755a2200c\",\"176\":\"07a4e45fc60c1660f6ed\",\"177\":\"9b428114a29614e108f2\",\"178\":\"147adeaf7c544b315f8e\",\"179\":\"ff892b6a3b756f63c40a\",\"180\":\"8be41a755870280cea1f\",\"181\":\"c34d39ecd273d283ba07\",\"182\":\"295e7c566d70137d7b27\",\"183\":\"78c1df1e2eeffe56cda0\",\"184\":\"0c6bd913265756d52797\",\"185\":\"75cefef1ae6e2376a860\",\"186\":\"a1478d1a9e81897deb22\",\"187\":\"93c6e4cf0deb9e5b2205\",\"188\":\"083103d6fdd03f82cbed\",\"189\":\"6f0ee849eb870d216fd0\",\"190\":\"18cc10312bf1a9136e27\",\"191\":\"4791c86b5c39421fe090\",\"192\":\"4086a88a796998d439cf\",\"193\":\"dd211444dede77412650\",\"194\":\"b8d4111ed1784be860ea\",\"195\":\"3e54bc6e3821bedf26f7\",\"196\":\"5fe45d7dc099c5996841\",\"197\":\"5a9e4e6ae32719d4aa39\",\"198\":\"2f9a2432ed918d82f47b\",\"199\":\"bc68b75da6827de0f32e\",\"200\":\"8a24c3119a79d779deb0\",\"201\":\"194f58f6040829b9ec67\",\"202\":\"bb9046a7ecdef9e7a9c2\",\"203\":\"fc339968cc3981b3180c\",\"204\":\"c2f8da26e089ec407e18\",\"205\":\"2ebd25036a7c7cbe0895\",\"206\":\"29d3eec75bc65e3f7da4\",\"207\":\"ba74338c2f6e1ecf3a63\",\"208\":\"c35ba76a2285716815c5\",\"209\":\"d49bc0c0186f362f4544\",\"210\":\"73dc8177b1866da9da56\",\"211\":\"19a2fd75152d2de783e8\",\"212\":\"737494643254c3e889e5\",\"213\":\"7ed4c9fd595719584561\",\"214\":\"221cf8847527ed2a29ab\",\"215\":\"122aaced22eb54033ec9\",\"216\":\"de765882306f37f43351\",\"217\":\"07920a6af97f7704920b\",\"218\":\"b88646387bf1ebaee247\",\"219\":\"09006184e39ccc1c1996\",\"220\":\"02d712860c5e7c4c0036\",\"221\":\"870e7451be2b7828a84b\",\"222\":\"fa984ffe024499809779\",\"223\":\"8776a62fc0c437bd2027\",\"224\":\"5bbd0007c482042bddf5\",\"225\":\"0a0131a7d323d74e77d1\",\"226\":\"7258093e1fb64caa69a8\",\"227\":\"49cad5499a0fe7b25278\",\"228\":\"7a5470830a7f1ca4ca42\",\"229\":\"373108c20429a8fbf572\",\"230\":\"542febf3ddf14f83a8f0\",\"231\":\"47883dea4b95b732bd04\",\"232\":\"547abc0a5849c4747117\",\"233\":\"c91e28e3226dab6e4f14\",\"234\":\"f0c9b42761a1a90204d2\",\"235\":\"04115aec78a26ec53a78\",\"236\":\"777427a7954abe53e946\",\"237\":\"ee2d442856d4a2163c98\",\"238\":\"6cd9cbe2431a47834507\",\"239\":\"a657377b1814d296af00\",\"240\":\"4a3477cd7843d1054b0f\",\"241\":\"63aca44a39ba0c6a2862\",\"242\":\"14f8505c84f0c1ac8e8e\",\"243\":\"793b13500231a4e4cec9\",\"244\":\"3fb687eed837f8c1455c\",\"245\":\"e281ca326e408d6045d1\"}[chunkId] + \".js\"\n \t}\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId) {\n \t\tvar promises = [];\n\n\n \t\t// JSONP chunk loading for javascript\n\n \t\tvar installedChunkData = installedChunks[chunkId];\n \t\tif(installedChunkData !== 0) { // 0 means \"already installed\".\n\n \t\t\t// a Promise means \"currently loading\".\n \t\t\tif(installedChunkData) {\n \t\t\t\tpromises.push(installedChunkData[2]);\n \t\t\t} else {\n \t\t\t\t// setup Promise in chunk cache\n \t\t\t\tvar promise = new Promise(function(resolve, reject) {\n \t\t\t\t\tinstalledChunkData = installedChunks[chunkId] = [resolve, reject];\n \t\t\t\t});\n \t\t\t\tpromises.push(installedChunkData[2] = promise);\n\n \t\t\t\t// start chunk loading\n \t\t\t\tvar script = document.createElement('script');\n \t\t\t\tvar onScriptComplete;\n\n \t\t\t\tscript.charset = 'utf-8';\n \t\t\t\tscript.timeout = 120;\n \t\t\t\tif (__webpack_require__.nc) {\n \t\t\t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n \t\t\t\t}\n \t\t\t\tscript.src = jsonpScriptSrc(chunkId);\n\n \t\t\t\t// create error before stack unwound to get useful stacktrace later\n \t\t\t\tvar error = new Error();\n \t\t\t\tonScriptComplete = function (event) {\n \t\t\t\t\t// avoid mem leaks in IE.\n \t\t\t\t\tscript.onerror = script.onload = null;\n \t\t\t\t\tclearTimeout(timeout);\n \t\t\t\t\tvar chunk = installedChunks[chunkId];\n \t\t\t\t\tif(chunk !== 0) {\n \t\t\t\t\t\tif(chunk) {\n \t\t\t\t\t\t\tvar errorType = event && (event.type === 'load' ? 'missing' : event.type);\n \t\t\t\t\t\t\tvar realSrc = event && event.target && event.target.src;\n \t\t\t\t\t\t\terror.message = 'Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';\n \t\t\t\t\t\t\terror.name = 'ChunkLoadError';\n \t\t\t\t\t\t\terror.type = errorType;\n \t\t\t\t\t\t\terror.request = realSrc;\n \t\t\t\t\t\t\tchunk[1](error);\n \t\t\t\t\t\t}\n \t\t\t\t\t\tinstalledChunks[chunkId] = undefined;\n \t\t\t\t\t}\n \t\t\t\t};\n \t\t\t\tvar timeout = setTimeout(function(){\n \t\t\t\t\tonScriptComplete({ type: 'timeout', target: script });\n \t\t\t\t}, 120000);\n \t\t\t\tscript.onerror = script.onload = onScriptComplete;\n \t\t\t\tdocument.head.appendChild(script);\n \t\t\t}\n \t\t}\n \t\treturn Promise.all(promises);\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/bundles/v1/hybrid/20200405.7/\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n \tvar jsonpArray = window[\"webpackJsonp\"] = window[\"webpackJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// add entry module to deferred list\n \tdeferredModules.push([892,0]);\n \t// run deferred modules when ready\n \treturn checkDeferredModules();\n","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * The app error object that contains the data of an app error\r\n */\r\nexport interface AppError {\r\n /** error id */\r\n id: number,\r\n\r\n /** source file */\r\n source?: string,\r\n\r\n /** Message or data */\r\n message?: string,\r\n\r\n /** severity */\r\n severity?: Severity,\r\n\r\n /** Property Bag */\r\n pb?: AppErrorPropertyBag\r\n}\r\n\r\n/**\r\n * The app error property bag that will be used for build number etc.\r\n */\r\nexport interface AppErrorPropertyBag {\r\n /** build number */\r\n build?: string,\r\n\r\n /** custom message */\r\n customMessage?: string\r\n}\r\n\r\n/**\r\n * The interface that defines a generic app error tracker\r\n */\r\nexport interface AppErrorTracker {\r\n /**\r\n * Report an app error\r\n * @param {AppError} error - the app error to report\r\n */\r\n trackError(error: AppError): Promise;\r\n}\r\n\r\n/**\r\n * This will decide whether to create Alert for this app error or no alert. This can generate IcM ticket.\r\n * Alerts ones are tracked at http://aka.ms/AppErrors\r\n * NoAlerts will have separate tab just next to Errors aka Warnings. IcM ticket won't be generated when NoAlert is set.\r\n */\r\nexport enum Severity {\r\n Alert,\r\n NoAlert,\r\n HighImpact\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { getRequestData } from \"./requestData\";\r\n\r\n/**\r\n * Checks if the DOM is available to access and use.\r\n * @returns {boolean} - true if DOM is available, or false if it is not. This is typically true for\r\n * client side rendering and false for server side rendering.\r\n */\r\nexport function canUseDOM(): boolean {\r\n return !!(typeof window !== \"undefined\" && window.document && window.document.createElement);\r\n}\r\n\r\n/**\r\n * Get window.location.href in an isomorphic manner.\r\n */\r\nexport function getLocationHref(): string {\r\n return canUseDOM() ? window.location.href : getRequestData().url.href;\r\n}\r\n\r\n/**\r\n * Get window.location.hostname in an isomorphic manner.\r\n */\r\nexport function getLocationHostname(): string {\r\n return canUseDOM() ? window.location.hostname : getRequestData().url.hostname;\r\n}\r\n\r\n/**\r\n * Get window.location.host in an isomorphic manner.\r\n */\r\nexport function getLocationHost(): string {\r\n return canUseDOM() ? window.location.host : getRequestData().url.host;\r\n}\r\n\r\n/**\r\n * Get window.location.origin in an isomorphic manner.\r\n */\r\nexport function getLocationOrigin(): string {\r\n return canUseDOM() ? window.location.origin : getRequestData().url.origin;\r\n}\r\n\r\n/**\r\n * Get window.location.search in an isomorphic manner.\r\n */\r\nexport function getLocationSearch(): string {\r\n return canUseDOM() ? window.location.search : getRequestData().url.search;\r\n}\r\n\r\n/**\r\n * Get window.location.pathname in an isomorphic manner.\r\n */\r\nexport function getLocationPathname(): string {\r\n return canUseDOM() ? window.location.pathname : getRequestData().url.pathname;\r\n}\r\n\r\n/**\r\n * Get window.location.protocol in an isomorphic manner.\r\n */\r\nexport function getLocationProtocol(): string {\r\n return canUseDOM() ? window.location.protocol : getRequestData().url.protocol;\r\n}\r\n\r\n/**\r\n * Get window.location.hash in an isomorphic manner.\r\n */\r\nexport function getLocationHash(): string {\r\n return canUseDOM() ? window.location.hash : getRequestData().url.hash;\r\n}\r\n\r\n/**\r\n * Get window.document.getElementById(elementId).\r\n */\r\nexport function getDocumentElementById(elementId: string): HTMLElement {\r\n if (!canUseDOM()) {\r\n throw new Error(\"getDocumentElementById is unsupported server side. This call should be wrapped in canUseDOM().\");\r\n }\r\n\r\n return window.document.getElementById(elementId);\r\n}\r\n\r\n/**\r\n * Get window.document.getDocumentElementsByTagName(elementId).\r\n */\r\nexport function getDocumentElementsByTagName(tagName: string): HTMLCollectionOf {\r\n if (!canUseDOM()) {\r\n throw new Error(\"getDocumentElementsByTagName is unsupported server side. This call should be wrapped in canUseDOM().\");\r\n }\r\n\r\n return window.document.getElementsByTagName(tagName);\r\n}\r\n\r\n/**\r\n * Get localStorage in an isomorphic manner.\r\n * Todo (http://osgvsowi/23753462), provide actual functionality for localStorage on the server side.\r\n */\r\nexport function getLocalStorage(): Storage {\r\n return canUseDOM() ? window.localStorage : null;\r\n}\r\n\r\n/**\r\n * Get indexedDB in an isomorphic manner.\r\n * Todo (http://osgvsowi/23753462), provide actual functionality for indexedDB on the server side.\r\n */\r\nexport function getIndexedDB(): IDBFactory {\r\n return canUseDOM() ? window.indexedDB : null;\r\n}\r\n\r\n/**\r\n * Get window.innerWidth in an isomorphic manner.\r\n * Todo (http://osgvsowi/23876778), remove the need for server to know about innerWidth by limiting layout options or use CSS based solution.\r\n */\r\nexport function getInnerWidth(): number {\r\n return canUseDOM() ? window.innerWidth : getRequestData().innerWidth;\r\n}\r\n\r\n/**\r\n * Get window.innerWidth in an isomorphic manner.\r\n * Todo (http://osgvsowi/23876778), remove the need for server to know about innerWidth by limiting layout options or use CSS based solution.\r\n */\r\nexport function getInnerHeight(): number {\r\n return canUseDOM() ? window.innerHeight : getRequestData().innerHeight;\r\n}\r\n\r\n/**\r\n * Get window.devicePixelRatio in an isomorphic manner.\r\n */\r\nexport function getDevicePixelRatio(): number {\r\n return canUseDOM() ? window.devicePixelRatio : getRequestData().devicePixelRatio;\r\n}\r\n\r\n/**\r\n * Get CSS Grid support in an isomorphic manner\r\n */\r\nexport function getCssGridSupport(): boolean {\r\n return !!(canUseDOM() ? (window.CSS && window.CSS.supports && CSS.supports(\"display\", \"grid\")) : getRequestData().canUseCssGrid);\r\n}\r\n\r\n/**\r\n * Get variable font support in an isomorphic manner\r\n * TODO: SSR currently does not support custom fonts.\r\n */\r\nexport function getVariableFontSupport(): boolean {\r\n if (!canUseDOM()) {\r\n throw new Error(\"SSR currently does not support custom fonts.\");\r\n }\r\n\r\n return !!(window.CSS && window.CSS.supports && CSS.supports(\"(font-variation-settings: normal)\"));\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * The aria-label html attribute\r\n * @type {string}\r\n */\r\nexport const ariaLabelAttribute: string = \"aria-label\";\r\n\r\n/**\r\n * The id attribute on the
element that is the root element for Peregrine Pages / Experiences.\r\n * There is only ever 1 root element on a page\r\n * @type {string}\r\n */\r\nexport const rootElementId: string = \"msnewsroot\";\r\n\r\n/**\r\n * Element names that are commonly used in Peregrine pages and experiences\r\n * @type {object}\r\n */\r\nexport const htmlElementIds: any = {\r\n html: \"html\",\r\n head: \"head\",\r\n body: \"body\"\r\n};\r\n\r\n/**\r\n * Constants used by application cache related scenarios\r\n */\r\nexport const applicationCacheConstants = {\r\n /**\r\n * Attribute name on html tag that is set when appcache is being used on the page\r\n */\r\n manifestAttributeName: \"manifest\",\r\n\r\n /**\r\n * Local storage key that holds the appcache info used to determine page refresh needs\r\n * for different page types.\r\n */\r\n pagesRefreshData: \"ac_prd\",\r\n\r\n /**\r\n * Local storage key that holds the appcache stored head data entries\r\n */\r\n storedHeadDataKey: \"ac_shd\",\r\n\r\n /**\r\n * Local storage key that holds the appcache stored activity IDs\r\n */\r\n storedLastUsedActivityIdKey: \"ac_sai\"\r\n\r\n};\r\n\r\n/**\r\n * The attributes that are part of markup elements that we care about\r\n */\r\nexport const clientSettings = \"data-client-settings\";\r\nexport const pagetypeSettings = \"data-pagetype\";\r\nexport const id = \"data-id\";\r\nexport const info = \"data-info\";\r\nexport const js = \"data-js\";\r\nexport const m = \"data-m\";\r\nexport const lang = \"lang\";\r\nexport const dir = \"dir\";\r\nexport const serviceUrl = \"data-service-url\";\r\nexport const telemetryId = \"data-telemetry-id\";\r\nexport const trackPageProduct = \"data-page-product\";\r\nexport const trackPageType = \"data-page-type\";\r\n\r\n/**\r\n * The number of characters that our Service Request Ids must have. This is currently defined by OneService\r\n * @type {number}\r\n */\r\nexport const numberOfCharactersNeededForUniqueRequestId: number = 32;\r\n\r\n/**\r\n * The minimum number of path segments that will be in the URL which hosts MS News Experience pages.\r\n * The first path segment should be the vertical key, e.g. spartan and the second path segment\r\n * should be the the category key, e.g. ntp\r\n * @type {number}\r\n */\r\nexport const minimumHostPagePathSegments: number = 2;\r\n\r\n/**\r\n * Default value we use for the name of the cookie that holds the ANID\r\n */\r\nexport const anonCookieName = \"APP_ANON\";\r\n\r\n/**\r\n * App Anon Cookie Exists Cookie Name. This cookie is a marker if APP_ANON exist or not.\r\n * This is necessary because APP_ANON is HTTP cookie and not accessible by JS.\r\n */\r\nexport const appAnonCookieExistsCookieName = \"aace\";\r\n\r\n/**\r\n * Child cookie name, used to signal if rpsUser is child account.\r\n */\r\nexport const childCookieName = \"child\";\r\n\r\n/**\r\n * Migration consent state cookie, indicates user has already granted or denied migration consent\r\n */\r\nexport const migrationConsentStateKey = \"migration-state\";\r\n\r\n/**\r\n * Id of MSCC cookie banner container element.\r\n */\r\nexport const msccCookieBannerElementId = \"consent-banner-container\";\r\n\r\n/**\r\n * used query string params in OneService requests\r\n */\r\nexport const oneServiceQueryStringKeys = {\r\n activityId: \"activityId\",\r\n apiKey: \"apikey\",\r\n complexInfoPaneEnabled: \"cipenabled\",\r\n contentType: \"contentType\",\r\n disableTypeSerialization: \"DisableTypeSerialization\",\r\n infopaneCount: \"infopaneCount\",\r\n fdhead: \"fdhead\",\r\n feedLayoutRequestType: \"t\",\r\n filter: \"$filter\",\r\n ids: \"ids\",\r\n location: \"location\",\r\n market: \"market\",\r\n ocid: \"ocid\",\r\n parentContentId: \"parent-content-id\",\r\n parentNamespace: \"parent-ns\",\r\n parentTitle: \"parent-title\",\r\n query: \"query\",\r\n queryType: \"queryType\",\r\n qScope: \"qscope\",\r\n responseSchema: \"responseschema\",\r\n select: \"$select\",\r\n signInCookieName: \"scn\",\r\n skip: \"$skip\",\r\n source: \"source\",\r\n timeOut: \"timeOut\",\r\n top: \"$top\",\r\n user: \"user\",\r\n wrapOData: \"wrapodata\"\r\n};\r\n\r\n/**\r\n * Constants to use as role attribute value for elements\r\n */\r\nexport enum AriaRoles {\r\n /**\r\n * Presentation role is used to remove semantic meaning from an element and any of its related child elements.\r\n */\r\n Presentation = \"presentation\"\r\n}\r\n\r\n/**\r\n * Enterprise compliant domain for One Service api\r\n */\r\nexport const EnterpriseOneServiceApi = \"https://ent-api.msn.com/\";\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { canUseDOM, getDocumentElementsByTagName, getLocationSearch } from \"@msnews/isomorphic-util\";\r\nimport { applicationCacheConstants, clientSettings, dir, htmlElementIds, info, js, lang, pagetypeSettings } from \"../constants\";\r\n\r\nimport { AudienceModeType } from \"@msnews/experiences-constants\";\r\nimport { DeviceFormFactorType } from \"cms-models-msn/configuration/types/DeviceFormFactorType\";\r\nimport { Environment } from \"./Environment\";\r\nimport { ILocale } from \"cms-models-msn/configuration/ILocale\";\r\nimport { IPcsBrowserScope } from \"../types/PcsBrowsersType\";\r\nimport { MarketProperties } from \"./MarketProperties\";\r\nimport { OperatingSystemType } from \"cms-models-msn/configuration/types/OperatingSystemType\";\r\nimport { UrlUtility } from \"../utilities/UrlUtility\";\r\nimport { localStorage } from \"../utilities/WebStorage\";\r\nimport { tryParseJson } from \"../utilities/Parsing\";\r\n\r\n/**\r\n * Format used for activity ID stored in storage\r\n */\r\nexport type StoredActivityId = {\r\n /**\r\n * ID value\r\n */\r\n id: string,\r\n\r\n /**\r\n * Timestamp of when value was stored\r\n */\r\n ts: number,\r\n\r\n /**\r\n * Flag inidicating if the ID was used in a previous page (stale)\r\n */\r\n previouslyUsed?: boolean\r\n};\r\n\r\n/**\r\n * JSON data contract / interface for settings in the element that are part of the data-client-settings attribute.\r\n */\r\nexport interface IClientSettings {\r\n aid: string,\r\n apptype: string,\r\n apps_locale: string,\r\n audienceMode?: AudienceModeType,\r\n browser?: IPcsBrowserScope,\r\n configRootUrl?: string,\r\n deviceFormFactor?: DeviceFormFactorType,\r\n domain?: string,\r\n env: Environment,\r\n featureFlags?: any,\r\n contentId?: string,\r\n\r\n /** The schema://domain to be used for the main feed URL */\r\n feedBaseDomain?: string,\r\n\r\n categoryKey?: string,\r\n functionalonly_cookie_experience: boolean,\r\n functional_cookie_patterns: string,\r\n functional_cookies: string,\r\n geo_city?: string,\r\n geo_country?: string,\r\n geo_countryname?: string;\r\n geo_lat: string,\r\n geo_long: string,\r\n geo_subdivision?: string,\r\n geo_zip?: string,\r\n locale?: ILocale,\r\n market?: MarketProperties,\r\n os?: OperatingSystemType,\r\n pagetype?: string,\r\n\r\n /** Query params in the format \"?key=value&...\" as observed from the PCS origin server */\r\n queryparams?: string,\r\n\r\n static_page?: string,\r\n verticalKey?: string,\r\n\r\n /** cache busting identifier sent by pcs */\r\n cbid?: string\r\n}\r\n\r\nexport const EnterpiseFlightId = \"prg-enterpriseblended-t\";\r\nexport const OfficeDefaultPivotFlightId = \"prg-officedefault-t\";\r\n\r\n/**\r\n * Class for getting the head data information.\r\n */\r\nclass HeadData {\r\n /**\r\n * The single instance of the HeadData class.\r\n * @type {HeadData}\r\n */\r\n private static _instance: HeadData;\r\n\r\n private anonCookieName: string;\r\n private locale: string;\r\n private marketDir: string;\r\n private currentFlights: string;\r\n private clientSettings: IClientSettings;\r\n private userIsSignedIn: boolean;\r\n private isPreload: boolean;\r\n private headElement: any;\r\n private htmlElement: any;\r\n private isAppcache: boolean;\r\n private isEnterprise: boolean;\r\n private isOfficeDefaultPivot: boolean;\r\n private isServiceWorkerCache: boolean;\r\n private ssoComplete: boolean;\r\n private aadState: boolean;\r\n\r\n private locationSearch: string;\r\n\r\n // TODO: Task 24890741: refactor this class to use the current singleton pattern with ES6 modules\r\n // This will also clean up these getters/setters\r\n public get Locale(): string { return this.locale; }\r\n public get MarketDir(): string { return this.marketDir; }\r\n public get CurrentFlights(): string { return this.currentFlights || \"\"; }\r\n public get ClientSettings(): IClientSettings { return this.clientSettings; }\r\n public get UserIsSignedIn(): boolean { return this.userIsSignedIn; }\r\n public get IsPreload(): boolean { return this.isPreload; }\r\n public get IsAppCache(): boolean { return this.isAppcache; }\r\n public get IsEnterprise(): boolean { return this.isEnterprise; }\r\n public get IsOfficeDefaultPivot(): boolean { return this.isOfficeDefaultPivot; }\r\n public get IsServiceWorkerCache(): boolean { return this.isServiceWorkerCache; }\r\n\r\n // TODO: Dependencies that some client side code expects headData to specify but doesn't due to PCS\r\n public get AnonCookieName(): string { return this.anonCookieName; }\r\n public get SsoComplete(): boolean { return this.ssoComplete; }\r\n public get AadState(): boolean { return this.aadState; }\r\n\r\n // For testing purposes add setters\r\n public set AnonCookieName(value: string) { this.anonCookieName = value; }\r\n public set LocaleName(value: string) { this.locale = value; }\r\n public set MarketDir(value: string) { this.marketDir = value; }\r\n public set CurrentFlights(value: string) { this.currentFlights = value; }\r\n public set ClientSettings(value: IClientSettings) { this.clientSettings = value; }\r\n public set IsEnterprise(value: boolean) { this.isEnterprise = value; }\r\n public set IsOfficeDefaultPivot(value: boolean) { this.isOfficeDefaultPivot = value; }\r\n public set UserIsSignedIn(value: boolean) { this.userIsSignedIn = value; }\r\n\r\n /**\r\n * Initialize the head data instance.\r\n */\r\n private constructor() {\r\n this.initializeHeadData();\r\n }\r\n\r\n /**\r\n * Returns singleton class instance.\r\n * @returns {HeadData}\r\n */\r\n public static getInstance(): HeadData { return HeadData._instance || (HeadData._instance = new HeadData()); }\r\n\r\n /**\r\n * Initialize the head data\r\n */\r\n public initializeHeadData(): void {\r\n this.locationSearch = getLocationSearch();\r\n this.htmlElement = canUseDOM() ? getDocumentElementsByTagName(htmlElementIds.html)[0] : null;\r\n this.headElement = canUseDOM() ? getDocumentElementsByTagName(htmlElementIds.head)[0] : null;\r\n\r\n if (!this.htmlElement || !this.headElement) {\r\n return;\r\n }\r\n\r\n // We always initialize from DOM first because\r\n // even if we are in an appcache/service worker case, we still need some data from the DOM\r\n // and we will fallback to DOM if there are no items found in storage\r\n this.initializeFromDom();\r\n\r\n // Attempt to override with local storage item when in appcache scenario\r\n // In service worker scenario, just update the storage activity id\r\n if (this.htmlElement.getAttribute(applicationCacheConstants.manifestAttributeName)) {\r\n this.isAppcache = true;\r\n this.initializeFromStorage();\r\n } else if (window && window.navigator && window.navigator.serviceWorker && window.navigator.serviceWorker.controller) {\r\n this.isServiceWorkerCache = true;\r\n this.updateStorageActivityId();\r\n }\r\n\r\n // Below items are common for both scenarios\r\n const language = this.htmlElement.getAttribute(lang);\r\n this.locale = language && language.toLowerCase() || \"\";\r\n\r\n const marketDir = this.htmlElement.getAttribute(dir);\r\n this.marketDir = marketDir && marketDir.toLocaleLowerCase() || \"\";\r\n\r\n // Test override to add flights for scope purposes\r\n if (location.hostname.toLowerCase().includes(\"localhost\")) {\r\n const queryItems = UrlUtility.getParamsWithItems(this.locationSearch);\r\n const flights = queryItems.find(item => item.key === \"flights\");\r\n if (flights) {\r\n this.currentFlights = flights.value;\r\n }\r\n }\r\n\r\n // Note: This isn't currently being stamped by PCS\r\n let headDataJs = this.headElement.getAttribute(js);\r\n if (headDataJs) {\r\n const headJs = <{ anonckname: string, signedin: number }>tryParseJson(headDataJs);\r\n this.anonCookieName = headJs.anonckname;\r\n this.userIsSignedIn = headJs.signedin === 1;\r\n }\r\n\r\n // Checks if current request is background preload request\r\n if (UrlUtility.getQueryParameterByName(\"backgroundpreload\", this.locationSearch)) {\r\n this.isPreload = true;\r\n }\r\n\r\n // We know we are in the Enterpise version of the page when both the audience mode is set to Enterprise\r\n // and the correct flight id is set.\r\n this.IsEnterprise = this.clientSettings &&\r\n this.currentFlights &&\r\n this.currentFlights.includes(EnterpiseFlightId) &&\r\n this.clientSettings.audienceMode === AudienceModeType.Enterprise;\r\n\r\n // There is work scheduled to have \"sticky\" pivots stored in some form of local storage which will\r\n // replace this check. Until then, the only way to know if Office is the default pivot is to check\r\n // for this flight id\r\n this.IsOfficeDefaultPivot = this.currentFlights && this.currentFlights.includes(OfficeDefaultPivotFlightId);\r\n }\r\n\r\n /**\r\n * Helper that gets the current's page stored last used activityID (if there is one)\r\n */\r\n public getCurrentPageTypeStoredActivityId(): StoredActivityId {\r\n const storedActivities = localStorage.getItem(applicationCacheConstants.storedLastUsedActivityIdKey) || \"\";\r\n const storedActivityIds = tryParseJson(storedActivities);\r\n\r\n return (storedActivityIds && storedActivityIds[headData.ClientSettings.pagetype]) || null;\r\n }\r\n\r\n /**\r\n * Initializes the client settings and info from DOM element\r\n */\r\n private initializeFromDom(): void {\r\n let dataClientSettings = this.headElement.getAttribute(clientSettings);\r\n if (dataClientSettings) {\r\n this.clientSettings = tryParseJson(dataClientSettings);\r\n\r\n // If clientSettings.pagetype does not exist, try getting from data-pagetype.\r\n // For Peregrine full spa page: pagetype is part of data-client-settings. There is no data-pagetype.\r\n // For Prime/Hybrid, pagetype is outside of data-client-settings and it belongs to data-pagetype\r\n if (!this.clientSettings.pagetype) {\r\n const pageTypeFromSettings = this.headElement.getAttribute(pagetypeSettings);\r\n this.clientSettings.pagetype = pageTypeFromSettings === null ? undefined : pageTypeFromSettings;\r\n }\r\n }\r\n this.setFlights(this.headElement.getAttribute(info));\r\n }\r\n\r\n /**\r\n * Initializes headData client settings and info from the value found in storage\r\n * and if none is found, fallbacks to using the DOM element\r\n */\r\n private initializeFromStorage(): void {\r\n const responseFromStorage = localStorage.getItem(applicationCacheConstants.storedHeadDataKey);\r\n const parsedResponseFromStorage = tryParseJson(responseFromStorage);\r\n\r\n // If there is nothing store, then fallback to the DOM\r\n if (!parsedResponseFromStorage) {\r\n return;\r\n }\r\n\r\n const currentPageStoredHeadData = parsedResponseFromStorage[this.clientSettings.pagetype];\r\n\r\n // We don't have an entry for the current page\r\n if (!currentPageStoredHeadData) {\r\n return;\r\n }\r\n\r\n const storedClientSettings = currentPageStoredHeadData[\"clientSettings\"];\r\n const storedFlights = currentPageStoredHeadData[\"info\"];\r\n\r\n // The stored head data is corrupt so we fallback to DOM\r\n if (!storedClientSettings || !storedFlights) {\r\n return;\r\n }\r\n\r\n this.clientSettings = storedClientSettings;\r\n this.setFlights(storedFlights);\r\n this.updateStorageActivityId();\r\n }\r\n\r\n /**\r\n * Update the last used activity ID in storage\r\n */\r\n private updateStorageActivityId(): void {\r\n if (!this.clientSettings.aid) {\r\n return;\r\n }\r\n\r\n const existingLastUsedActivityIds = tryParseJson(localStorage.getItem(applicationCacheConstants.storedLastUsedActivityIdKey)) || {};\r\n const currentPageLastUsedActivityId: StoredActivityId = existingLastUsedActivityIds[this.clientSettings.pagetype];\r\n\r\n // If the current pages last used activity ID matches the one for the current page head data\r\n // then we have re-used this. Mark it as such but don't override the timestamp\r\n if (currentPageLastUsedActivityId && (currentPageLastUsedActivityId.id === this.clientSettings.aid)) {\r\n currentPageLastUsedActivityId.previouslyUsed = true;\r\n existingLastUsedActivityIds[this.clientSettings.pagetype] = currentPageLastUsedActivityId;\r\n } else {\r\n // If they don't match then that means we haven't used this so store the new value.\r\n const activityIdToStore: StoredActivityId = { id: this.clientSettings.aid, ts: (new Date()).getTime() };\r\n existingLastUsedActivityIds[this.clientSettings.pagetype] = activityIdToStore;\r\n }\r\n\r\n // Update the last used activity ID in storage\r\n localStorage.setItem(applicationCacheConstants.storedLastUsedActivityIdKey, JSON.stringify(existingLastUsedActivityIds));\r\n }\r\n\r\n /**\r\n * Parses flights from provided string (if in proper format of f:{flights})\r\n * and sets it to the headData object\r\n */\r\n private setFlights(flightString: string): void {\r\n // The comma separated list of flights enabled in current request\r\n this.currentFlights = ((/f:\\s*([^;]+)/i.exec(flightString) || {})[1] || \"\").toLowerCase();\r\n }\r\n}\r\n\r\nexport let getHeadData = HeadData.getInstance;\r\nexport let headData = HeadData.getInstance();","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { IActionPayload } from \"./IActionPayload\";\r\nimport { IDataConnector } from \"../connectors\";\r\nimport PageBase from \"../pages/PageBase\";\r\n\r\n/**\r\n * Helper function to create an action payload\r\n * @param connector The connector (if applicable) where the action will be dispatched\r\n * @param type The Action Type (name of the action)\r\n * @param args Arguments to be passed to the action\r\n * @param experienceInstanceId If defined, the id of an experience instance, that will be used by action receiver\r\n */\r\nexport function getActionPayload(connector: IDataConnector, type: string, args: any[], experienceInstanceId: string): IActionPayload {\r\n let stateKey: string = undefined;\r\n if (connector) {\r\n if (!connector.parentNamespace) {\r\n stateKey = connector.namespace;\r\n } else {\r\n stateKey = connector.parentNamespace + \".\" + connector.namespace;\r\n }\r\n }\r\n\r\n return {\r\n key: stateKey,\r\n experienceInstanceId: experienceInstanceId,\r\n type: type,\r\n params: args\r\n };\r\n}\r\n\r\n/**\r\n * Helper function to dispatch an action either to a connector's namespaced store, or to the root store for the entire app.\r\n * @param connector The connector (if applicable) where the action will be dispatched\r\n * @param payload The action payload\r\n */\r\nexport function dispatchAction(connector: IDataConnector, payload: IActionPayload): any {\r\n\r\n // Dispatch the action\r\n if (connector) {\r\n return connector.store.dispatch(payload);\r\n } else {\r\n return PageBase.getInstance().store.dispatch(payload);\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { IActionDispatchCancellationToken } from \"./IActionDispatchCancellationToken\";\r\n\r\n/**\r\n * Cancellation Token class.\r\n * @class\r\n */\r\nexport class ActionDispatchCancellationToken implements IActionDispatchCancellationToken {\r\n /** Backing variable for the isCancellationRequested property\r\n * @type {boolean}\r\n */\r\n private isCancelled: boolean;\r\n\r\n /**\r\n * Creates an instance of the `ActionDispatchCancellationToken` class.\r\n * @constructor\r\n */\r\n constructor() {\r\n this.isCancelled = false;\r\n }\r\n\r\n /**\r\n * Helper method to cater for a null or undefined token.\r\n * A null or undefined token means cancellation cannot be requested, so it is equivalent to false\r\n * @method\r\n * @param {IActionDispatchCancellationToken} cancellationToken Optional cancellation token to be checked for undefined, null or cancellation requested\r\n * @returns {boolean}\r\n */\r\n public static isCancellationRequested(cancellationToken?: IActionDispatchCancellationToken): boolean {\r\n return !(cancellationToken === undefined || cancellationToken === null || !cancellationToken.isCancellationRequested);\r\n }\r\n\r\n /** The cancel method.\r\n * @method\r\n */\r\n public cancel(): void {\r\n this.isCancelled = true;\r\n }\r\n\r\n /** getter for the isCancellationRequested property\r\n * @property\r\n * @returns {boolean} Whether cancellation has been requested or not.\r\n */\r\n public get isCancellationRequested(): boolean {\r\n return this.isCancelled;\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { dispatchAction, getActionPayload } from \"./ActionDispatchHelper\";\r\n\r\nimport { ActionDispatchCancellationToken } from \"./ActionDispatchCancellationToken\";\r\nimport { ConnectorConstants } from \"../constants/ConnectorConstants\";\r\nimport { IActionDispatchCancellationToken } from \"./IActionDispatchCancellationToken\";\r\nimport { IActionPayload } from \"./IActionPayload\";\r\nimport { Observer } from \"./ActionObserver\";\r\nimport { PerfTimeline } from '@msnews/diagnostics';\r\n\r\n/**\r\n * Class that wraps the sending of a action to a connector (i.e. dispatch) with an explicit method, so that in the consuming code\r\n * it is obvious that the action is being \"sent\"\r\n * @class\r\n */\r\nexport abstract class ActionSenderBase {\r\n /**\r\n * Property which is a function that will send an action to the connector.\r\n */\r\n public get send(): TActionSignature {\r\n return (this.dispatchAction());\r\n }\r\n\r\n /**\r\n * Creates an instance of the `ActionSender` class.\r\n * @constructor\r\n * @param {string} type The action type.\r\n * @param {IActionDispatchCancellationToken} cancellationToken Optional cancellation token, which can be used to cancel an in flight action\r\n */\r\n constructor(\r\n protected type: string,\r\n private observers: Observer[],\r\n private cancellationToken?: IActionDispatchCancellationToken) { }\r\n\r\n /**\r\n * Method to get dispatcher and payload\r\n * @param args - the arguments being dispatched\r\n * @returns dispatch result metadata\r\n */\r\n protected abstract getDispatchResult(args: any[]): { payload: IActionPayload, result: any };\r\n\r\n /**\r\n * Gets the perf timeline object if applicable\r\n */\r\n protected abstract tryGetPerfTimeline(): PerfTimeline;\r\n\r\n /**\r\n * Method that returns an action sender function to send the action.\r\n * @method\r\n * @return {TActionSignature} return value is a function to send to action.\r\n */\r\n private dispatchAction(): TActionSignature {\r\n return function (): any {\r\n if (!ActionDispatchCancellationToken.isCancellationRequested(this.cancellationToken)) {\r\n\r\n const perfTimeline = this.tryGetPerfTimeline();\r\n let actionEndMeasure = perfTimeline && perfTimeline.startMeasure(\"action\", this.type).endMeasure;\r\n\r\n const { payload, dispatchResult } = this.getDispatchResult(Array.prototype.slice.call(arguments));\r\n\r\n // Call any observers\r\n this.observers.forEach(o => {\r\n try {\r\n // Call the observer\r\n o.observer(payload);\r\n } catch (error) {\r\n console.log(`Error calling observer: ${JSON.stringify(o)}, with error: ${error}`);\r\n }\r\n\r\n // If there is a connector, dispatch an action to it, forcing it to re-render\r\n if (o.connector) {\r\n let renderActionPayload = getActionPayload(o.connector, ConnectorConstants.renderAction, [], undefined);\r\n dispatchAction(o.connector, renderActionPayload);\r\n }\r\n });\r\n\r\n if (actionEndMeasure) {\r\n actionEndMeasure();\r\n }\r\n\r\n // Return the dispatch result\r\n return dispatchResult;\r\n } else {\r\n // Don't dispatch the action because it has been canceled\r\n return;\r\n }\r\n };\r\n }\r\n\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { dispatchAction, getActionPayload } from \"./ActionDispatchHelper\";\r\n\r\nimport { ActionSenderBase } from \"./ActionSenderBase\";\r\nimport { IActionDispatchCancellationToken } from \"./IActionDispatchCancellationToken\";\r\nimport { IActionPayload } from \"./IActionPayload\";\r\nimport { IDataConnector } from \"../connectors\";\r\nimport { Observer } from \"./ActionObserver\";\r\nimport { PerfTimeline } from '@msnews/diagnostics';\r\n\r\n/**\r\n * Class that wraps the sending of a action to a connector (i.e. dispatch) with an explicit method, so that in the consuming code\r\n * it is obvious that the action is being \"sent\"\r\n * @class\r\n */\r\nexport class ActionSender extends ActionSenderBase {\r\n\r\n /**\r\n * Creates an instance of the `ActionSender` class.\r\n * @constructor\r\n * @param {string} type The action type.\r\n * @param {IDataConnector} connector The connector instance to dispatch the action to.\r\n * @param {IActionDispatchCancellationToken} cancellationToken Optional cancellation token, which can be used to cancel an in flight action\r\n */\r\n constructor(\r\n type: string,\r\n observers: Observer[],\r\n private connector: IDataConnector,\r\n cancellationToken?: IActionDispatchCancellationToken) {\r\n\r\n super(type, observers, cancellationToken);\r\n }\r\n\r\n /**\r\n * Core dispatch implementation for {GlobalActionSender}\r\n * @param args - the arguments being dispatched\r\n * @returns dispatch result metadata\r\n */\r\n protected getDispatchResult(args: any[]): { payload: IActionPayload, result: any } {\r\n let payload = getActionPayload(this.connector, this.type, args, undefined);\r\n let result = dispatchAction(this.connector, payload);\r\n return { payload, result };\r\n }\r\n\r\n /**\r\n * Gets the perf timeline if applicable\r\n */\r\n protected tryGetPerfTimeline(): PerfTimeline {\r\n return this.connector.perfTimeline;\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { PerfTimeline, tryGetPerfTimeline } from '@msnews/diagnostics';\r\nimport { dispatchAction, getActionPayload } from \"./ActionDispatchHelper\";\r\n\r\nimport { ActionSenderBase } from \"./ActionSenderBase\";\r\nimport { IActionDispatchCancellationToken } from \"./IActionDispatchCancellationToken\";\r\nimport { IActionPayload } from './IActionPayload';\r\nimport { Observer } from \"./ActionObserver\";\r\n\r\n/**\r\n * Class that wraps the sending of a action globally to all connectors\r\n * @export\r\n * @class\r\n */\r\nexport class GlobalActionSender extends ActionSenderBase {\r\n\r\n /**\r\n * Creates an instance of the `GlobalActionSender` class.\r\n * @constructor\r\n * @param {string} type The action type.\r\n * @param {string} experienceInstanceId Optional experienceInstanceId of the experience that is originating the action.\r\n * @param {IActionDispatchCancellationToken} cancellationToken Optional cancellation token, which can be used to cancel an in flight action.\r\n */\r\n constructor(\r\n type: string,\r\n observers: Observer[],\r\n private experienceInstanceId?: string,\r\n cancellationToken?: IActionDispatchCancellationToken) {\r\n\r\n super(type, observers, cancellationToken);\r\n }\r\n\r\n /**\r\n * Core dispatch implementation for {GlobalActionSender}\r\n * @param args - the arguments being dispatched\r\n * @returns dispatch result metadata\r\n */\r\n protected getDispatchResult(args: any[]): { payload: IActionPayload, result: any } {\r\n let payload = getActionPayload(undefined, this.type, args, this.experienceInstanceId);\r\n let result = dispatchAction(undefined, payload);\r\n return { payload, result };\r\n }\r\n\r\n /**\r\n * Gets the perf timeline if applicable\r\n */\r\n protected tryGetPerfTimeline(): PerfTimeline {\r\n return tryGetPerfTimeline(\"GlobalActionSender\", this.experienceInstanceId || \"unknown\");\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ActionObserver, Observer } from \".\";\r\n\r\nimport { ActionSender } from \"./ActionSender\";\r\nimport { GlobalActionSender } from \"./GlobalActionSender\";\r\nimport { IActionDispatchCancellationToken } from \"./IActionDispatchCancellationToken\";\r\nimport { IActionMap } from \"./IActionMap\";\r\nimport { IDataConnector } from \"../connectors/IDataConnector\";\r\nimport PageBase from \"../pages\";\r\n\r\n/**\r\n * Class that maps Action to its callback function type.\r\n * Provides the method to get action creator which returns callback function to send to action.\r\n * Callback function dispatches the action payload.\r\n * @class\r\n */\r\nexport class ActionMap implements IActionMap {\r\n\r\n /**\r\n * An array of registered action observers\r\n */\r\n private observers: Observer[] = [];\r\n\r\n /**\r\n * Creates an instance of the `ActionMap` class.\r\n * @constructor\r\n * @param {string} type The action type, which is part of the IActionMap contract.\r\n */\r\n constructor(public type: string) {\r\n }\r\n\r\n /**\r\n * Method that returns an action sender function that can be used to send/dispatch the action to a specific connector\r\n * @method\r\n * @param {IDataConnector | string} connector The connector instance to send the action to, or the connector namespace. If the param type\r\n * is string, then the connector instance will be looked up, and used if found.\r\n * @param {IActionDispatchCancellationToken} cancellationToken If passed in and cancellation has been requested, then nothing is dispatched.\r\n * @return {TActionSignature} return value is an object with a send method, which is used to send the action.\r\n */\r\n public getActionSender(connector: IDataConnector | string, cancellationToken?: IActionDispatchCancellationToken): ActionSender | undefined {\r\n let connectorInstance: IDataConnector = undefined;\r\n if (typeof(connector) === \"string\") {\r\n // Find the connector with the matching namespace\r\n connectorInstance = PageBase.getInstance().rootReducer.connector(connector);\r\n } else {\r\n connectorInstance = connector;\r\n }\r\n\r\n if (connectorInstance) {\r\n return new ActionSender(this.type, this.observers, connectorInstance, cancellationToken);\r\n }\r\n }\r\n\r\n /**\r\n * Method that returns an action sender function that can be used to send/dispatch the action globally to all connectors\r\n * @method\r\n * @param {string} experienceInstanceId An optional experienceInstanceId, that will get passed along in the action payload.\r\n * It can then be used by the receiving reducer to determine if the action should be handled.\r\n * @param {IActionDispatchCancellationToken} cancellationToken If passed in and cancellation has been requested, then nothing is dispatched.\r\n * @return {TActionSignature} return value is an object with a send method, which is used to send the action.\r\n */\r\n public getGlobalActionSender(experienceInstanceId?: string, cancellationToken?: IActionDispatchCancellationToken): GlobalActionSender {\r\n return new GlobalActionSender(this.type, this.observers, experienceInstanceId, cancellationToken);\r\n }\r\n\r\n /**\r\n * Method that registers a new observer for this action. The observer will be called after the action is dispatched\r\n * @method\r\n * @param {ActionObserver} observer The observer to be added to the list of observers that will be called when the action completes\r\n */\r\n public registerObserver(observer: ActionObserver, connector?: IDataConnector): void {\r\n this.observers.push({ observer: observer, connector: connector });\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { KeyValueArray, KeyValuePair, Utility } from \"./Utility\";\r\nimport { findIndex, isArray, isEmpty, isString, trimEnd, trimStart } from \"lodash-es\";\r\n\r\nimport { StringMap } from \"../types\";\r\nimport { getLocationOrigin } from \"@msnews/isomorphic-util\";\r\n\r\nexport namespace UrlUtility {\r\n\r\n /**\r\n * Characters that, if present on a url, will make prime routing misbehave\r\n *\r\n * These are the characters we know cause problems:\r\n * - spaces\r\n * - slashes\r\n * - punctuation: !?.:\r\n * - ampersands\r\n *\r\n * As we don't know all the offending characters, we are just removing every character that is not alphanumeric\r\n */\r\n const primeForbiddenCharacters: RegExp = /[^A-Za-z0-9]+/g;\r\n\r\n /**\r\n * Parse parameters from the given URL\r\n * @param {string} url - the URL to parse for parameters\r\n * @param {boolean} decodeComponents - flag to indicate whether the query param key and value should be URL decoded\r\n * @returns {KeyValueArray} - the parsed query key/value collection\r\n */\r\n export function getParamsFromUrl(url: string, decodeComponents: boolean = false): KeyValueArray {\r\n if (!isString(url)) {\r\n return null;\r\n }\r\n\r\n let queryString: string = (url || \"\").split(\"?\")[1];\r\n return getParams(queryString, decodeComponents);\r\n }\r\n\r\n /**\r\n * Decode the given URL encoded string that may contain plus signs\r\n * @param {string} val - The value to decode.\r\n * @returns {string} - the decoded value\r\n */\r\n function decodeURIComponentWithPlusSign(val: string): string {\r\n val = val.replace(/\\+/g, \" \");\r\n val = decodeURIComponent(val);\r\n return val;\r\n }\r\n\r\n /**\r\n * Encode uri components in a way that won't break prime routing system\r\n * @param uriComponent the uriComponent to be encoded\r\n */\r\n export function encodeURIComponentForPrime(uriComponent: string): string {\r\n return encodeURIComponent(uriComponent.replace(primeForbiddenCharacters, \"-\"));\r\n }\r\n\r\n /**\r\n * Parse parameters from the given query string\r\n * @param {string} queryString - the query string to parse for parameters\r\n * @param {boolean} decodeComponents - flag to indicate whether the query param key and value should be URL decoded\r\n * @returns {KeyValueArray} - the parsed query key/value collection\r\n */\r\n export function getParams(queryString: string, decodeComponents: boolean = false): KeyValueArray {\r\n\r\n let params: KeyValueArray = [];\r\n\r\n if (queryString) {\r\n // remove hash part.\r\n queryString = queryString.split(\"#\")[0];\r\n let queryArray = queryString.split(\"&\");\r\n for (let ndx = 0; ndx < queryArray.length; ndx++) {\r\n let parts = queryArray[ndx].split(\"=\");\r\n let queryKey = parts[0];\r\n let queryValue = parts[1];\r\n\r\n if (decodeComponents) {\r\n queryKey = decodeURIComponentWithPlusSign(queryKey);\r\n if (queryValue) {\r\n queryValue = decodeURIComponentWithPlusSign(queryValue);\r\n }\r\n }\r\n\r\n // Don't allow for duplicate query string parameter keys. Take the last one\r\n let newParam: KeyValuePair = { key: queryKey, value: queryValue };\r\n let existingParam = findIndex(params, (entry) => entry.key === newParam.key);\r\n if (existingParam === -1) {\r\n params.push(newParam);\r\n } else {\r\n params[existingParam] = newParam;\r\n }\r\n }\r\n }\r\n return params;\r\n }\r\n\r\n /**\r\n * Parse parameters from the given query string, allowing for multiple item=key:value\r\n * @param {string} queryString - the query string to parse for parameters\r\n * @returns {KeyValueArray} - the parsed query key/value collection\r\n */\r\n export function getParamsWithItems(queryString: string): KeyValueArray {\r\n let params: KeyValueArray = [];\r\n\r\n if (queryString) {\r\n // Remove the leading ? if it is present\r\n if (queryString.startsWith(\"?\")) {\r\n queryString = queryString.substring(1);\r\n }\r\n\r\n // split on the hashes.\r\n queryString = queryString.split(\"#\")[0];\r\n let queryArray = queryString.split(\"&\");\r\n for (let ndx = 0; ndx < queryArray.length; ndx++) {\r\n let parts = queryArray[ndx].split(\"=\");\r\n let queryKey = parts[0];\r\n let queryValue = parts[1];\r\n\r\n // If the query key is \"item\", and the query values is key:value, then convert the\r\n // value into the actual key/value\r\n if (queryKey.toLowerCase() === \"item\") {\r\n let queryItems = queryValue.split(\":\");\r\n if (queryItems.length === 2) {\r\n queryKey = queryItems[0];\r\n queryValue = queryItems[1];\r\n }\r\n }\r\n\r\n // Don't allow for duplicate query string parameter keys. Take the last one\r\n let newParam: KeyValuePair = { key: queryKey, value: queryValue };\r\n let existingParam = findIndex(params, (entry) => entry.key === newParam.key);\r\n if (existingParam === -1) {\r\n params.push(newParam);\r\n } else {\r\n params[existingParam] = newParam;\r\n }\r\n }\r\n }\r\n return params;\r\n }\r\n\r\n /**\r\n * Utility method to extract query string param in url.\r\n *\r\n * @export\r\n * @param {string} name - query param name\r\n * @returns {string} - query param value\r\n */\r\n export function getQueryParameterByName(name: string, href: string): string {\r\n\r\n // TODO: exposing this method for accessing a single parameter can be used\r\n // extremely inefficiently (for example if invoked multiple times to get parameters\r\n // from a single URL). Instead we should deprecate this and export getParamsObj\r\n // and use that throughout.\r\n\r\n let value = getParamsObj(href)[name];\r\n return (value !== undefined)\r\n ? value\r\n : null;\r\n }\r\n\r\n /**\r\n * Check if given url string is a valid url.\r\n * Returns true when url string is a valid url, otherwise false.\r\n *\r\n * @export\r\n * @param url {string} - Url string value to check\r\n * @param validateScheme {boolean} - Should scheme validation be forced\r\n * @return {boolean}\r\n */\r\n export function isValidUrl(url: string, validateScheme: boolean): boolean {\r\n return (isString(url) &&\r\n (url.length > 0) &&\r\n (!validateScheme ||\r\n validateScheme && url.indexOf(\"http\") === 0));\r\n }\r\n\r\n /**\r\n * Converts a keyValueArray into a set of query string parameters\r\n *\r\n * @export\r\n * @param {any} - params to be converted\r\n * @return {string}\r\n */\r\n export function keyValueArrayToQueryString(params: KeyValueArray): string {\r\n // Validate we have a nonempty array\r\n if (!isArray(params) || isEmpty(params)) {\r\n return \"\";\r\n }\r\n\r\n // Filter for valid keyValue entries, and then map them into key==value strings\r\n // joined with an &\r\n const queryString: string = params.filter(kv =>\r\n Utility.isKeyValuePair(\r\n kv,\r\n (key) => typeof (key) === \"string\",\r\n (value) => typeof (value) === \"string\"))\r\n .map(kv => kv.key + \"=\" + kv.value)\r\n .join(\"&\");\r\n\r\n return queryString;\r\n }\r\n\r\n /**\r\n * Helper method to parse the given URLs query parameters to a lookup dictionary\r\n * @param url - the URL string with the query params to parse\r\n * @returns The {StringMap} containing the key/value pairs, or empty object.\r\n */\r\n function getParamsObj(url: string): StringMap {\r\n let paramsObj = {};\r\n let paramArray = getParamsFromUrl(url, true);\r\n if (paramArray && paramArray.length) {\r\n paramArray.forEach(keyValuePair =>\r\n paramsObj[keyValuePair.key] = keyValuePair.value);\r\n }\r\n return paramsObj;\r\n }\r\n\r\n /**\r\n * For the given `url`, it appends the `subPath` to it.\r\n * It takes propers care to forward slashes characters\r\n * at the end of `url` and at the start of `subPath` parameters\r\n * @param url a valid url\r\n * @param subPath the path which is appended to `url`\r\n * @returns an URL object which is the `url` appended by `subPath`\r\n */\r\n export function joinSubpathToURL(url: URL, subPath: string): URL {\r\n const href = url.href;\r\n const trimmedEndSlashFromHref = trimEnd(href, \"/\");\r\n const trimmedStartSlashFromSubpath = trimStart(subPath, \"/\");\r\n return new URL(`${trimmedEndSlashFromHref}/${trimmedStartSlashFromSubpath}`);\r\n }\r\n\r\n /**\r\n * Updates a search parameter in the given url to map to a new value\r\n * Does not modify the url if the given search param doesn't exist\r\n * @param url the url to update\r\n * @param key the name of the search param to be updated\r\n * @param value the new value for the given search param\r\n * @returns {URL} the updated URL\r\n */\r\n export function updateSearchParam(url: URL, key: string, value: string): URL {\r\n // Note that the searchParams data member may not be compatible with older browser versions\r\n // see https://caniuse.com/#search=searchparams\r\n if (url && url.searchParams && url.searchParams.get(key)) {\r\n url.searchParams.set(key, value);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Appends a search parameter to the given url\r\n * @param url the url to modify\r\n * @param key the name of the search param to be appended\r\n * @param value the new value for the given search param\r\n * @returns {URL} the modified URL\r\n */\r\n export function appendSearchParam(url: URL, key: string, value: string, fallback?: boolean): URL {\r\n if (url) {\r\n if (url.searchParams || fallback) {\r\n url.searchParams.append(key, value);\r\n } else {\r\n // TODO Bug 22390312: [Peregrine] UrlUtility appendSearchParam needs more robust polyfill\r\n url = new URL(url.href + (url.search.indexOf(\"?\") >= 0 ? \"&\" : \"?\") + key + \"=\" + value);\r\n }\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Returns an absolute URL if a relative on is passed in, or returns the passed in URL if already absolute\r\n * @param partialUrl The relative or absolute URL\r\n * @returns {string} the absolute URL\r\n */\r\n export function getAbsoluteUrl(partialUrl: string): string {\r\n if (partialUrl.indexOf('://') > 0 || partialUrl.indexOf('//') === 0) {\r\n return partialUrl;\r\n } else {\r\n return getLocationOrigin() + partialUrl;\r\n }\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Constants that are used throughout the library\r\n */\r\nexport namespace ConnectorConstants {\r\n /**\r\n * The key within a state JSON document used to store a connectors individual state\r\n */\r\n export const connectorStateKey: string = \"_@STATE@_\";\r\n\r\n export const renderAction: string = \"@@connector-view/RENDER\";\r\n\r\n export const dataConnectorMergeInitAction: string = \"@@data-connector/MERGE-INIT\";\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Client side properties that Render Service sends to initialize RequestData.\r\n * These properties are typically passed via query param to the render service.\r\n * On the client side these are available and populated through the DOM.\r\n */\r\nexport interface RequestProps {\r\n\r\n /**\r\n * URL for the original client request.\r\n */\r\n href: string;\r\n\r\n /**\r\n * Width of client browser window.\r\n */\r\n innerWidth: number;\r\n\r\n /**\r\n * Height of client browser window.\r\n */\r\n innerHeight: number;\r\n\r\n /**\r\n * Device pixel ratio of client.\r\n */\r\n devicePixelRatio: number;\r\n\r\n /**\r\n * CSS Grid support of the client browser.\r\n */\r\n canUseCssGrid: boolean;\r\n\r\n /**\r\n * Request Id.\r\n */\r\n requestId: number;\r\n}\r\n\r\n/**\r\n * Singleton class to store client browser data sent through query param to Render Service.\r\n * This is only used under server environment.\r\n */\r\nclass RequestData {\r\n /**\r\n * The single instance of the RequestData class.\r\n * @type {RequestData}\r\n */\r\n private static _instance: RequestData = null;\r\n\r\n /**\r\n * URL object to be used to store original request url.\r\n */\r\n public readonly url: URL;\r\n\r\n /**\r\n * Inner width of browser from the original request.\r\n */\r\n public readonly innerWidth: number;\r\n\r\n /**\r\n * Inner height of browser from the original request.\r\n */\r\n public readonly innerHeight: number;\r\n\r\n /**\r\n * Device pixel ratio from the original request.\r\n */\r\n public readonly devicePixelRatio: number;\r\n\r\n /**\r\n * Boolean flag that represents if CSS Grid is supported by the browser from the original request.\r\n */\r\n public readonly canUseCssGrid: boolean;\r\n\r\n /**\r\n * Request Id.\r\n */\r\n public readonly requestId: number;\r\n\r\n /**\r\n * Initialize the request data instance with passed in client properties\r\n */\r\n private constructor(data: RequestProps) {\r\n this.url = new URL(data.href);\r\n this.innerWidth = data.innerWidth;\r\n this.innerHeight = data.innerHeight;\r\n this.devicePixelRatio = data.devicePixelRatio;\r\n this.canUseCssGrid = data.canUseCssGrid;\r\n this.requestId = data.requestId;\r\n }\r\n\r\n /**\r\n * Returns singleton class instance.\r\n * @returns RequestData\r\n */\r\n public static getInstance(): RequestData {\r\n if (global[\"TEST_ENV\"] && !RequestData._instance) {\r\n resetRequestData({\r\n href: \"http://localhost:8080/\",\r\n innerWidth: 1024,\r\n innerHeight: 768,\r\n devicePixelRatio: 1,\r\n canUseCssGrid: false,\r\n requestId: 0\r\n });\r\n }\r\n\r\n if (!RequestData._instance) {\r\n // Throw error if the request data has not been set as this should never be the case.\r\n // This likely highlights that the request data was not initialized when handling a\r\n // request when server side rendering.\r\n throw new Error(\"Request data is not initialized yet through ResetInstance.\");\r\n }\r\n return RequestData._instance;\r\n }\r\n\r\n /**\r\n * Reset singleton class instance with passed in info and client settings\r\n * @returns RequestData\r\n */\r\n public static resetInstance(data: RequestProps): RequestData {\r\n RequestData._instance = new RequestData(data);\r\n return RequestData._instance;\r\n }\r\n}\r\n\r\n/**\r\n * Export function to reset the request data singleton.\r\n * This must be used to set the request data.\r\n */\r\nexport const resetRequestData = RequestData.resetInstance;\r\n\r\n/**\r\n * Export get instance function for testing\r\n */\r\nexport const getRequestData = () => (RequestData.getInstance());","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { AadData, clientId, oneServiceScope } from \"./Enterprise\";\r\nimport { AccountType, AppType, AudienceModeType, AuthCookieName } from \"@msnews/experiences-constants\";\r\nimport { EnterpriseOneServiceApi, appAnonCookieExistsCookieName, childCookieName, rootElementId, serviceUrl, telemetryId, trackPageProduct, trackPageType } from \"../constants\";\r\nimport { Environment, getEnvironmentFromString } from \"./Environment\";\r\nimport { HostPage, IHostPage } from \"./HostPage\";\r\nimport { canUseDOM, getDocumentElementById, getLocationHref, getLocationOrigin, getLocationSearch } from \"@msnews/isomorphic-util\";\r\nimport { getCookie, getMuidCookie } from \"../utilities/CookieUtility\";\r\n\r\nimport { Market } from \"./Market\";\r\nimport { PageRequestTargetScope } from \"./PageRequestTargetScope\";\r\nimport { PlatformType } from \"cms-models-msn/configuration/types/PlatformType\";\r\nimport { UrlUtility } from \"../utilities/UrlUtility\";\r\nimport { Utility } from \"../utilities/Utility\";\r\nimport { headData } from \"./HeadData\";\r\nimport { isString } from \"lodash-es\";\r\nimport { logger } from \"@msnews/diagnostics\";\r\n\r\n/**\r\n * chrome\r\n * The chrome API is not defined in Typescript\r\n */\r\ndeclare global {\r\n // tslint:disable-next-line: completed-docs\r\n interface Window { chrome: any; }\r\n}\r\n\r\n/**\r\n * Page level experience tracking info\r\n */\r\nexport interface ITrackInfo {\r\n sitePage: {\r\n page_product: string,\r\n page_type: string\r\n }\r\n}\r\n\r\nexport class AppEnvironment {\r\n /**\r\n * The single instance of the AppEnvironment class.\r\n * @type {AppEnvironment}\r\n */\r\n private static _instance: AppEnvironment;\r\n\r\n /**\r\n * the activity id for the current page view\r\n */\r\n private activityId: string;\r\n\r\n /**\r\n * Base url for the content service, endpoints/queries are appended for specific content calls.\r\n * This is an akamai url for highly cacheable content.\r\n * Possible values are enumerated on ContentServiceConfig.ts\r\n *\r\n * @private\r\n * @type {string}\r\n * @memberof AppEnvironment\r\n */\r\n private contentServiceUrlBase: URL;\r\n\r\n private currentRequestTargetScope: PageRequestTargetScope;\r\n\r\n private currentMarket: Market;\r\n private hostPage: IHostPage;\r\n\r\n /** The hostname to use for content links. */\r\n private currentContentLinkHost: string;\r\n\r\n /**\r\n * Indicates that the page is running as an FRE page (i.e. the url contains fre=1)\r\n * Does not indicate that the FRE itself is currently displayed over the page.\r\n */\r\n private isFrePage: boolean;\r\n\r\n /**\r\n * Base for the service url, endpoints/queries are appended for specific service calls.\r\n * This is the OneService url used for personalized content.\r\n * Possible values are enumerated on OneServiceConfig.ts\r\n *\r\n * @private\r\n * @type {string}\r\n * @memberof AppEnvironment\r\n */\r\n private serviceUrlBase: URL;\r\n\r\n /**\r\n * Base URL for the feed service\r\n */\r\n private feedServiceUrlBase: URL;\r\n\r\n /**\r\n * The account type of the page user\r\n * Currently this is only implemented for the Anaheim New Tab Pages\r\n */\r\n private accountType: AccountType;\r\n\r\n /**\r\n * The aad data for the current page user\r\n */\r\n private aadData: AadData;\r\n\r\n private appType: string;\r\n private authCookieName: AuthCookieName;\r\n private environmentConfigUrl: URL;\r\n\r\n private rootTelemetryId: number;\r\n private trackInfo: ITrackInfo;\r\n private userId: string;\r\n private countryCode: string;\r\n private latitude: string;\r\n private longitude: string;\r\n private environment: Environment;\r\n private featureFlags: any;\r\n private disableCachingConfigs: boolean;\r\n private enableConfigService: boolean;\r\n private isMultiConfigRetrievalEnabled: boolean;\r\n private configServiceBaseUrl: URL;\r\n private disableContentPreviewCache: boolean;\r\n private disableContentCacheIDBRead: boolean;\r\n\r\n /** True if query string has appropriate debug flag */\r\n private isDebug: boolean;\r\n\r\n /** True if query string has appropriate flag to show msnCreatorDashboard (msnDash=) */\r\n private showMnsCreatorDashboard: boolean;\r\n\r\n /** Config Root Url */\r\n private configRootUrl: URL;\r\n\r\n /** Cache busting identifier received from pcs */\r\n private cacheBustingIdentifier: string;\r\n\r\n /**\r\n * ActivityId value from initial server response, use telemetry's requestId instead for associating with current page client navigation\r\n */\r\n public get ActivityId(): string { return this.activityId; }\r\n\r\n /**\r\n * Getter for the base url for the content service, endpoints/queries are appended for specific content calls.\r\n * This is an akamai url for highly cacheable content.\r\n * Possible values are enumerated on ContentServiceConfig.ts\r\n *\r\n * @readonly\r\n * @type {URL}\r\n * @memberof AppEnvironment\r\n */\r\n public get EnvironmentConfigUrl(): URL {\r\n // If I mutate the same object, I will need to revert to the original state somewhere.\r\n // For safety reason, it is better to use a new Object\r\n const url = new URL(\"\", this.environmentConfigUrl);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(getLocationSearch()).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.config\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(getLocationSearch()).get(\"env.config\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.config\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Getter for the base url for the content service, endpoints/queries are appended for specific content calls.\r\n * This is an akamai url for highly cacheable content.\r\n * Possible values are enumerated on ContentServiceConfig.ts\r\n *\r\n * @readonly\r\n * @type {URL}\r\n * @memberof AppEnvironment\r\n */\r\n public get ContentServiceUrlBase(): URL {\r\n // If I mutate the same object, I will need to revert to the original state somewhere.\r\n // For safety reason, it is better to use a new Object\r\n const url = new URL(\"\", this.contentServiceUrlBase);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(getLocationSearch()).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.content\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(getLocationSearch()).get(\"env.content\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.content\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n public get CurrentRequestTargetScope(): PageRequestTargetScope { return this.currentRequestTargetScope; }\r\n public get CurrentMarket(): Market { return this.currentMarket; }\r\n public get Environment(): Environment { return this.environment; }\r\n public get HostPage(): IHostPage { return this.hostPage; }\r\n public get AppType(): string { return this.appType; }\r\n public get AuthCookieName(): AuthCookieName { return this.authCookieName; }\r\n public get AccountType(): AccountType { return this.accountType; }\r\n public get AadData(): AadData { return this.aadData; }\r\n\r\n /** True if query string has appropriate debug flag */\r\n public get IsDebug(): boolean { return this.isDebug; }\r\n\r\n /** True if query string has appropriate flag to show msnCreatorDashboard (msnDash=) */\r\n public get ShowMnsCreatorDashboard(): boolean { return this.showMnsCreatorDashboard; }\r\n\r\n /**\r\n * Gets the host to use when linking to content.\r\n */\r\n public get contentLinkHost(): string { return this.currentContentLinkHost; }\r\n\r\n /**\r\n * Getter for the base for the service url, endpoints/queries are appended for specific service calls.\r\n * This is the oneservice url used for personalized content.\r\n * Possible values are enumerated on OneServiceConfig.ts\r\n *\r\n * @type {URL}\r\n * @memberof AppEnvironment\r\n */\r\n public get ServiceUrlBase(): URL {\r\n const url = new URL(\"\", this.serviceUrlBase);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(getLocationSearch()).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.service\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(getLocationSearch()).get(\"env.service\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.service\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Base URL for the feed service\r\n */\r\n public get FeedServiceUrlBase(): URL {\r\n const url = new URL(\"\", this.feedServiceUrlBase);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(getLocationSearch()).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.service\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(getLocationSearch()).get(\"env.service\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.service\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Base URL for the enterprise service\r\n */\r\n public get EnterpriseServiceUrlBase(): URL {\r\n const url = new URL(\"\", EnterpriseOneServiceApi);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(location.search).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.service\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(location.search).get(\"env.service\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.service\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n public get IsFrePage(): boolean { return this.isFrePage; }\r\n\r\n public get RootTelemetryId(): number { return this.rootTelemetryId; }\r\n public get TrackInfo(): ITrackInfo { return this.trackInfo; }\r\n public get UserId(): string { return this.userId; }\r\n\r\n /**\r\n * This is the switch to turn on/off indexed db operation used as a caching layer in config resolver (Resolver.ts)\r\n */\r\n public get DisableCachingConfigs(): boolean { return this.disableCachingConfigs; }\r\n\r\n /**\r\n * This is the switch to turn on/off config service operation in Resolver.ts\r\n */\r\n public get EnableConfigService(): boolean { return this.enableConfigService; }\r\n\r\n /**\r\n * Check whether multi config retrieval is supported.\r\n */\r\n public get IsMultiConfigRetrievalEnabled(): boolean { return this.isMultiConfigRetrievalEnabled; }\r\n\r\n /**\r\n * This is the switch to turn on/off content preview caching in core/cache/ContentPreview.ts\r\n */\r\n public get DisableContentPreviewCache(): boolean {\r\n return this.disableContentPreviewCache;\r\n }\r\n\r\n /**\r\n * This is the switch to turn off hydrating content preview cache from IndexedDB.\r\n * Default is false\r\n */\r\n public get DisableContentCacheIDBRead(): boolean {\r\n const queryParamOverride = UrlUtility.getQueryParameterByName(\"disableContentCacheIDBRead\", getLocationSearch());\r\n\r\n if (queryParamOverride) {\r\n return queryParamOverride === \"true\";\r\n }\r\n\r\n return this.disableContentCacheIDBRead;\r\n }\r\n\r\n /**\r\n * Get base url of Config Service.\r\n */\r\n public get ConfigServiceBaseUrl(): URL { return this.configServiceBaseUrl; }\r\n\r\n /**\r\n * This returns feature flags client settings stamped by PCS.\r\n */\r\n public get FeatureFlags(): any { return this.featureFlags; }\r\n\r\n /**\r\n * This returns config root url\r\n */\r\n public get ConfigRootUrl(): URL {\r\n if (!this.configRootUrl) {\r\n return null;\r\n }\r\n\r\n const url = new URL(\"\", this.configRootUrl);\r\n\r\n if (process.env.WEBPACK_DEV_SERVER || new URLSearchParams(getLocationSearch()).get(\"env\") === \"dev\") {\r\n url.searchParams.set(\"env.config\", \"dev\");\r\n }\r\n\r\n const searchParam = new URLSearchParams(getLocationSearch()).get(\"env.config\");\r\n if (searchParam) {\r\n url.searchParams.set(\"env.config\", searchParam);\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Returns cache busting identifier from PCS.\r\n */\r\n public get CacheBustingIdentifier(): string { return this.cacheBustingIdentifier; }\r\n\r\n /**\r\n * Returns the country code. For example \"br\"\r\n */\r\n public get CountryCode(): string { return this.countryCode; }\r\n\r\n //// FIXME: hyphen has a second 'h'\r\n //// Bug 24228723: [Peregrine] ActivityIdLowerCaseNoHypens misspells \"Hyphen\"\r\n /**\r\n * Gets the Activity ID in lower case and without any hyphens. This helper method should be where parity with Prime is required.\r\n * Use telemetry's requestId instead for associating with current page client navigation\r\n */\r\n public get ActivityIdLowerCaseNoHypens(): string { return ((headData && headData.ClientSettings && headData.ClientSettings.aid) || \"\").toLowerCase(); }\r\n\r\n /**\r\n * Returns the latitude. For example \"42.361145\"\r\n */\r\n public get Latitude(): string { return this.latitude; }\r\n\r\n /**\r\n * Returns the longitude. For example \"-71.057083\"\r\n */\r\n public get Longitude(): string { return this.longitude; }\r\n\r\n public set ActivityId(value: string) { this.activityId = value; }\r\n public set CountryCode(value: string) { this.countryCode = value; }\r\n public set CurrentMarket(value: Market) { this.currentMarket = value; }\r\n public set CurrentRequestTargetScope(value: PageRequestTargetScope) { this.currentRequestTargetScope = value; }\r\n public set Environment(value: Environment) { this.environment = value; }\r\n public set HostPage(value: IHostPage) { this.hostPage = value; }\r\n public set RootTelemetryId(value: number) { this.rootTelemetryId = value; }\r\n public set TrackInfo(value: ITrackInfo) { this.trackInfo = value; }\r\n public set UserId(value: string) { this.userId = value; }\r\n public set AuthCookieName(value: AuthCookieName) { this.authCookieName = value; }\r\n public set AccountType(value: AccountType) { this.accountType = value; }\r\n public set AadData(value: AadData) { this.aadData = value; }\r\n\r\n /**\r\n * Initialize the AppConfig singleton instance\r\n */\r\n private constructor(serviceUrl: URL) {\r\n this.initializeAppEnvironment(serviceUrl);\r\n }\r\n\r\n /**\r\n * Returns singleton class instance.\r\n * @returns {AppEnvironment}\r\n */\r\n public static getInstance(serviceUrl: URL = null): AppEnvironment { return AppEnvironment._instance || (AppEnvironment._instance = new AppEnvironment(serviceUrl)); }\r\n\r\n /**\r\n * Initializes App environment. This is normally only called by the constructor (singleton pattern)\r\n * It is made public so that it can be also called by test code.\r\n */\r\n public initializeAppEnvironment(_serviceUrl?: URL): void {\r\n\r\n let environmentFromHeadData: Environment = null;\r\n const clientSettings = headData && headData.ClientSettings;\r\n\r\n if (clientSettings) {\r\n this.activityId = this.tryReformatGuid(clientSettings.aid);\r\n this.currentMarket = (headData.Locale || clientSettings.apps_locale) as Market;\r\n this.countryCode = clientSettings.geo_country;\r\n this.latitude = clientSettings.geo_lat;\r\n this.longitude = clientSettings.geo_long;\r\n this.configRootUrl = clientSettings.configRootUrl ? new URL(\"\", clientSettings.configRootUrl) : null;\r\n environmentFromHeadData = getEnvironmentFromString(clientSettings.env);\r\n\r\n this.setAccountType();\r\n this.appType = clientSettings.apptype || \"\";\r\n this.authCookieName = this.getAuthCookieName();\r\n\r\n this.featureFlags = clientSettings.featureFlags;\r\n\r\n this.disableCachingConfigs =\r\n this.featureFlags && this.featureFlags.disableCachingConfigs\r\n ? this.featureFlags.disableCachingConfigs === \"true\"\r\n : false;\r\n\r\n this.enableConfigService =\r\n this.featureFlags && this.featureFlags.enableConfigService\r\n ? this.featureFlags.enableConfigService === \"true\"\r\n : true;\r\n\r\n this.disableContentPreviewCache =\r\n this.featureFlags && this.featureFlags.disableContentPreviewCache\r\n ? this.featureFlags.disableContentPreviewCache === \"true\"\r\n : false;\r\n\r\n this.disableContentCacheIDBRead = this.featureFlags && this.featureFlags.disableContentCacheIDBRead\r\n ? this.featureFlags.disableContentCacheIDBRead === \"true\"\r\n : false;\r\n\r\n this.cacheBustingIdentifier = clientSettings.cbid;\r\n }\r\n\r\n const rootElement = canUseDOM() ? getDocumentElementById(rootElementId) : null;\r\n const locationHref = getLocationHref();\r\n const locationOrigin = getLocationOrigin();\r\n\r\n // env is read from\r\n // - query string param env, if present\r\n // - headData.ClientSettings.env\r\n // - defaults to prod otherwise\r\n const envQSOverwrite = getEnvironmentFromString(UrlUtility.getQueryParameterByName(\"env\", locationHref));\r\n this.environment =\r\n envQSOverwrite\r\n || environmentFromHeadData\r\n || Environment.prod;\r\n\r\n this.serviceUrlBase = _serviceUrl || (rootElement && rootElement.getAttribute(serviceUrl) && new URL(\"\", rootElement.getAttribute(serviceUrl))) || new URL(\"\", \"https://assets.msn.com/service/\");\r\n\r\n // If PCS sent the feed base domain, use it for the feed URL base\r\n // or else default to host page rooted URL.\r\n this.feedServiceUrlBase = new URL(\"./service/\", clientSettings && clientSettings.feedBaseDomain ? clientSettings.feedBaseDomain : locationOrigin);\r\n\r\n // Get the hostPage from the request url\r\n this.hostPage = HostPage.getHostPageFromUrl(locationHref);\r\n\r\n // Determine if the page is running as an FRE page\r\n this.isFrePage = (UrlUtility.getQueryParameterByName(\"fre\", locationHref) === \"1\");\r\n\r\n // Get the UserMuid from the muid cookie\r\n const muidCookie: string = getMuidCookie();\r\n if (isString(muidCookie)) {\r\n logger.log(\"u: m-\" + muidCookie);\r\n this.userId = \"m-\" + muidCookie;\r\n }\r\n\r\n // Get attributes from the head (full page Peregrine experience) or from the spa \"root\" element (PrimeHybrid case)\r\n // TODO, determine where in the element attributes these values should be set\r\n this.rootTelemetryId = rootElement ? Number(rootElement.getAttribute(telemetryId)) : 0;\r\n const trackPageProd = rootElement && rootElement.getAttribute(trackPageProduct);\r\n const trackPageTypeVal = rootElement && rootElement.getAttribute(trackPageType);\r\n this.trackInfo = { sitePage: { page_product: trackPageProd, page_type: trackPageTypeVal } };\r\n\r\n this.contentServiceUrlBase = new URL(\"\", \"https://assets.msn.com/content/\");\r\n\r\n this.currentContentLinkHost = this.createContentLinkHost();\r\n\r\n this.setTargetScope();\r\n\r\n this.isMultiConfigRetrievalEnabled = this.useMultiConfigsRetrieval();\r\n\r\n this.configServiceBaseUrl = new URL(\"\", this.getConfigServiceBaseUrl(this.isMultiConfigRetrievalEnabled));\r\n\r\n this.environmentConfigUrl = new URL(\"\", \"https://assets.msn.com/config/v1/\");\r\n\r\n this.isDebug = ((UrlUtility.getQueryParameterByName(\"debug\", locationHref) || \"\").toLowerCase() in { \"1\": 1, \"true\": 1 })\r\n || (UrlUtility.getQueryParameterByName(\"item\", locationHref) || \"\").toLowerCase().indexOf(\"/debug\") > 0;\r\n\r\n this.showMnsCreatorDashboard = UrlUtility.getQueryParameterByName(\"mnsDash\", locationHref) != null;\r\n }\r\n\r\n /**\r\n * Get config service base url\r\n * @param {isMultiConfigRetrievalEnabled} - if multiple config retrieval is supported.\r\n * @returns {string} - config service base url.\r\n */\r\n private getConfigServiceBaseUrl(isMultiConfigRetrievalEnabled: boolean = true): string {\r\n const relativePath = `/resolver/api/resolve/${isMultiConfigRetrievalEnabled ? `v2/` : ``}configindex/`;\r\n\r\n // int and localhost to use int.msn.com for config service.\r\n if (process.env.WEBPACK_DEV_SERVER || this.environment === Environment.int) {\r\n return \"https://int.msn.com\" + relativePath;\r\n }\r\n\r\n return getLocationOrigin() ? (getLocationOrigin() + relativePath) : null;\r\n }\r\n\r\n /**\r\n * Function checks if ConfigService should return multiple configs\r\n * @returns true if supported else false.\r\n */\r\n private useMultiConfigsRetrieval(): boolean {\r\n const urlQuery = getLocationSearch();\r\n if (urlQuery) {\r\n const param = UrlUtility.getQueryParameterByName(\"isMultiConfigRetrievalEnabled\", urlQuery);\r\n if (param) {\r\n return param.toLocaleLowerCase() === \"true\";\r\n }\r\n }\r\n\r\n // PCS flag to turn on/off multi config retrieval.\r\n if (this.featureFlags\r\n && this.featureFlags.isMultiConfigRetrievalEnabled) {\r\n return this.featureFlags.isMultiConfigRetrievalEnabled === \"true\";\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the auth cookie name based on the app type of the page\r\n * @returns {AuthCookieName} - the name of the auth cookie to use\r\n */\r\n private getAuthCookieName(): AuthCookieName {\r\n const clientSettings = headData && headData.ClientSettings;\r\n const appType: AppType = (clientSettings.apptype || \"\") as AppType;\r\n let authCookieName: AuthCookieName;\r\n switch (appType) {\r\n case AppType.Hub:\r\n case AppType.MicrosoftNews:\r\n case AppType.Views:\r\n authCookieName = AuthCookieName.Anon;\r\n break;\r\n case AppType.Edge:\r\n case AppType.EdgeChromium:\r\n case AppType.MMX:\r\n case AppType.Office:\r\n default:\r\n authCookieName = AuthCookieName.AppAnon;\r\n }\r\n\r\n return authCookieName;\r\n }\r\n\r\n /**\r\n * Sets the AccountType for the current user\r\n */\r\n private setAccountType(): void {\r\n if (!canUseDOM() || !window.chrome || !window.chrome.authPrivate || !window.chrome.authPrivate.getPrimaryAccountInfo) {\r\n this.AccountType = AccountType.SignedOut;\r\n return;\r\n }\r\n\r\n window.chrome.authPrivate.getPrimaryAccountInfo((accountInfo) => {\r\n if (!accountInfo) {\r\n this.AccountType = AccountType.SignedOut;\r\n return;\r\n }\r\n\r\n const accountType: string = accountInfo.account_type;\r\n if (accountType === \"AAD\") {\r\n this.AccountType = AccountType.AAD;\r\n this.setAadData();\r\n return;\r\n }\r\n\r\n if (accountType === \"MSA\") {\r\n this.AccountType = AccountType.MSA;\r\n return;\r\n }\r\n\r\n this.AccountType = AccountType.SignedOut;\r\n });\r\n }\r\n\r\n /**\r\n * Sets the AadData for the current user if an aad account\r\n */\r\n private setAadData(): void {\r\n if (!canUseDOM() || !window.chrome || !window.chrome.authPrivate) {\r\n return;\r\n }\r\n\r\n window.chrome.authPrivate.getPrimaryAccountInfo((accountInfo) => {\r\n if (!accountInfo) {\r\n return;\r\n }\r\n\r\n const tokenAcquireParameters = {\r\n account_id: accountInfo.account_id,\r\n account_type: accountInfo.account_type,\r\n client_id: clientId,\r\n scope_or_resource: oneServiceScope\r\n };\r\n\r\n window.chrome.authPrivate.acquireAccessTokenSilently(tokenAcquireParameters, (acquireResult) => {\r\n this.AadData = {\r\n token: acquireResult.access_token,\r\n errorInfo: acquireResult.error_info,\r\n isSuccess: acquireResult.is_success,\r\n isValid: acquireResult.is_token_valid\r\n };\r\n\r\n return;\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Determines the content link host to use.\r\n * @returns The content link host.\r\n */\r\n private createContentLinkHost(): string {\r\n const topLevelDomain = this.currentMarket === Market.ZHCN ? \"cn\" : \"com\";\r\n return \"www.msn.\" + topLevelDomain;\r\n }\r\n\r\n /**\r\n * Reformats the given guid without dashes to a guid string with dashes.\r\n * @param {string} guid - The guid without dashes.\r\n * @returns {string} - The reformatted GUI with dashes.\r\n */\r\n private tryReformatGuid(guid: string): string {\r\n if (guid && guid.length === 32) {\r\n // use a regex to extract the specific substrings to reformat the guid\r\n const matches = guid.match(/(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})/i);\r\n if (matches) {\r\n // join all the captured groups from 1-5 to format the final guid string\r\n guid = matches.slice(1).join(\"-\");\r\n }\r\n }\r\n\r\n return guid;\r\n }\r\n\r\n /**\r\n * Sets target scope for current request.\r\n */\r\n private setTargetScope(): void {\r\n if (!headData || !headData.ClientSettings) {\r\n return;\r\n }\r\n\r\n // If user is signed in and \"child\" Cookie exists - set Kids audience mode, otherwise use PCS provided Audience mode.\r\n const audienceMode = getCookie(appAnonCookieExistsCookieName) && getCookie(childCookieName) ? AudienceModeType.Kids : headData.ClientSettings.audienceMode;\r\n\r\n const { browser, deviceFormFactor, domain, locale, os, pagetype } = headData.ClientSettings;\r\n\r\n this.currentRequestTargetScope = {\r\n audienceMode: audienceMode,\r\n browser: browser,\r\n deviceFormFactor: deviceFormFactor,\r\n domain: domain,\r\n locale: locale,\r\n os: os,\r\n platform: PlatformType.Web,\r\n pageType: pagetype\r\n };\r\n\r\n // if locale is not defined in client settings, try reading it from headData for backward compatibility\r\n if (!this.currentRequestTargetScope.locale && Utility.stringHasData(headData.Locale)) {\r\n const locale = headData.Locale.split(\"-\");\r\n if (locale.length > 1) {\r\n this.currentRequestTargetScope.locale = {\r\n language: locale[0],\r\n // Some spartan locale are in format \"ha-latn-ng\". Here the market is \"ng\" and language is \"ha\"\r\n market: locale[locale.length - 1]\r\n };\r\n }\r\n }\r\n\r\n if (Utility.stringHasData(headData.CurrentFlights)) {\r\n this.currentRequestTargetScope.pageExperiments = headData.CurrentFlights.split(\",\");\r\n }\r\n }\r\n}\r\n\r\nexport const getAppEnvironment = AppEnvironment.getInstance;\r\nexport const appEnvironment = AppEnvironment.getInstance();","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { AppError, AppErrorPropertyBag, Severity } from \"./AppErrorTracker\";\r\n\r\n/**\r\n * This file contains the list of errors to log to the server for each feature.\r\n * We are centralizing errors here to make sure we do not have any dupes\\conflicts.\r\n * The idea is that each feature would have their own range of values.\r\n *\r\n * IMPORTANT: Please do not add strings to this file. Please map messages to send in your\r\n * code.\r\n */\r\n\r\n/**\r\n * All app errors are set to create IcM ticket by default unless specified in individual error code otherwise.\r\n */\r\nconst severity = Severity.Alert;\r\n\r\n// Webpack defines the BUILD_NUMBER of client code build number.\r\ndeclare var BUILD_NUMBER: string;\r\n\r\n/**\r\n * Get build number from web pack. If not present, return empty\r\n */\r\nconst pb: AppErrorPropertyBag = {\r\n build: typeof BUILD_NUMBER === \"undefined\"\r\n ? \"\"\r\n : BUILD_NUMBER\r\n};\r\n\r\n/** Represents a ServiceUI related error */\r\nexport const ServiceUiError: AppError = {\r\n id: 5100,\r\n source: \"ServiceUiComm.ts\",\r\n severity,\r\n pb\r\n};\r\n\r\n/** Represents a Top Sites related error */\r\nexport const TopSitesError: AppError = {\r\n id: 8010,\r\n source: \"TopSites.tsx\",\r\n severity,\r\n pb\r\n};\r\n\r\n/** Represents a Top Sites error when there are zero rendered top sites */\r\nexport const ZeroTopSitesError: AppError = {\r\n id: 8011,\r\n source: \"TopSites.connector.ts\",\r\n severity,\r\n pb\r\n};\r\n\r\n/** Curated sites list is empty */\r\nexport const CuratedSitesEmpty: AppError = {\r\n id: 8012,\r\n source: \"TopSites.connector.ts\",\r\n severity,\r\n pb\r\n};\r\n\r\nconst TopSitesEdgeConnectorFileName: string = \"TopSitesEdge.connector.tsx\";\r\nconst TopSitesEdgeStorageFileName: string = \"TopSitesStorage.ts\";\r\n\r\nexport const TopSitesEdgeAppErrors = {\r\n ZeroTopSitesError: {\r\n id: 8013,\r\n source: TopSitesEdgeConnectorFileName,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n CuratedSitesEmpty: {\r\n id: 8014,\r\n source: TopSitesEdgeStorageFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n ComponentMountFailed: {\r\n id: 8015,\r\n source: TopSitesEdgeConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n ErrorFetchingRichTopSitesDataCollectionFromCms: {\r\n id: 8016,\r\n source: TopSitesEdgeStorageFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst TopSitesEdgeNextConnectorFileName: string = \"TopSitesEdgeNext.connector.tsx\";\r\n\r\nexport const TopSitesEdgeNextAppErrors = {\r\n\r\n /** The React component failed to mount */\r\n ComponentMountFailed: {\r\n id: 8020,\r\n source: TopSitesEdgeNextConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Represents a Top Sites error when there are zero rendered top sites */\r\n ZeroTopSitesError: {\r\n id: 8021,\r\n source: TopSitesEdgeNextConnectorFileName,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nexport const TopSiteDialogAppErrors = {\r\n /** The React component failed to mount */\r\n TopSitesDialogFailedToMount: {\r\n id: 8025,\r\n source: \"TopSitesDialog.tsx\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst OneServiceCardProviderFileName: string = \"OneServiceCardProvider.ts\";\r\n\r\nexport const OneServiceCardProviderAppErrors = {\r\n OneServiceResponseWasNullOrErroneous: {\r\n id: 8031,\r\n source: OneServiceCardProviderFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n ErrorFetchingOneServiceResponse: {\r\n id: 8032,\r\n source: OneServiceCardProviderFileName,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n\r\n InvalidJsonInOneServiceResponse: {\r\n id: 8033,\r\n source: OneServiceCardProviderFileName,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n\r\n InvalidFeedListInOneServiceResponse: {\r\n id: 8034,\r\n source: OneServiceCardProviderFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n RiverConfigurationIssue: {\r\n id: 8035,\r\n source: OneServiceCardProviderFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load views river content based on current vertical/category. */\r\n QueryInterestContentFetchError: {\r\n id: 8036,\r\n source: OneServiceCardProviderFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n StaticContentLoaded: {\r\n id: 8037,\r\n source: OneServiceCardProviderFileName,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nconst ContentPreviewSourceFile = \"ContentPreview.connector.ts\";\r\nconst ContentPreviewDataSourceFile = \"ContentPreviewData.ts\";\r\nconst ExternalContentMapperHelperFile = \"ExternalContentMapperHelper.ts\";\r\n\r\nexport const ContentPreviewAppErrors = {\r\n\r\n ErrorWhileFetchingContentPreviewContent: {\r\n id: 8041,\r\n source: ContentPreviewDataSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n InvalidResponseFromContentPreviewFetch: {\r\n id: 8042,\r\n source: ContentPreviewDataSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n InvalidResponseFromContentPreviewResponseJson: {\r\n id: 8043,\r\n source: ContentPreviewDataSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n ErrorWhileInitializingAsyncContentPreviewContent: {\r\n id: 8044,\r\n source: ContentPreviewSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n InvalidOrMissingContentId: {\r\n id: 8045,\r\n source: ContentPreviewDataSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n MissingDataForExternalContent: {\r\n id: 8046,\r\n source: ExternalContentMapperHelperFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nconst RiverSourceFile = \"River.connector.ts\";\r\n\r\nexport const RiverAppErrors = {\r\n UnknownMetadataReceivedFromRiverCardProvider: {\r\n id: 8051,\r\n source: RiverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n RiverContentProviderFetchException: {\r\n id: 8052,\r\n source: RiverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n UnableToSelectSectionTemplateForGivenChildExperiences: {\r\n id: 8053,\r\n source: RiverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n InvalidConfig: {\r\n id: 8054,\r\n source: RiverSourceFile,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n\r\n ChildLoadError: {\r\n id: 8056,\r\n source: RiverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n InitialDataLoadError: {\r\n id: 8057,\r\n source: RiverSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst UserInitiatedPageRefreshSourceFile = \"UserInitiatedPageRefresh.ts\";\r\nexport const UserInitiatedPageRefreshErrors = {\r\n Default: {\r\n id: 8060,\r\n source: UserInitiatedPageRefreshSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst PivotContentSourceFile = \"PivotContent.connector.ts\";\r\nexport const PivotContentErrors = {\r\n LoadFailure: {\r\n id: 8070,\r\n source: PivotContentSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst PivotsNavSourceFile = \"PivotsNav.connector.ts\";\r\nexport const PivotsNavErrors = {\r\n TopicDataConnectorUnavailable: {\r\n id: 8075,\r\n source: PivotsNavSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n NavigationDataConnectorUnavailable: {\r\n id: 8076,\r\n source: PivotsNavSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n DynamicPivotsHelperLoaderFailed: {\r\n id: 8077,\r\n source: PivotsNavSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n LayoutPreferenceDataConnectorUnavailable: {\r\n id: 8078,\r\n source: PivotsNavSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Smart list is empty */\r\nexport const SmartListEmpty: AppError = {\r\n id: 8080,\r\n source: \"SmartList.connector.ts\",\r\n severity,\r\n pb\r\n};\r\n\r\n/** Represents BingWebSSO related App errors */\r\nconst BingWebSSOSourceFile = \"BingWebSSO.tsx\";\r\nexport const BingWebSSOAppErrors = {\r\n /** Failed to render bing websso iframe */\r\n BingWebSSORenderFailed: {\r\n id: 8090,\r\n source: BingWebSSOSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** User signed-in to MSA on page but bing SSO returned authentication failed response */\r\n BingWebSSOSignInFailed: {\r\n id: 8091,\r\n source: BingWebSSOSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Bing SSO process did not complete withing required time */\r\n BingWebSSOTimeout: {\r\n id: 8092,\r\n source: BingWebSSOSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst WeatherDataConnectorSourceFile = \"WeatherData.connector.ts\";\r\nexport const WeatherDataAppErrors = {\r\n /** Failed to fetch weather summary */\r\n WeatherSummaryFetchError: {\r\n id: 8100,\r\n source: WeatherDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** No valid Location set from User */\r\n WeatherLocationEmpty: {\r\n id: 8101,\r\n source: WeatherDataConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** Not able to read from PDP */\r\n WeatherPDPReadFailed: {\r\n id: 8102,\r\n source: WeatherDataConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** Not able to write home location to PDP */\r\n WeatherPDPHomeLocationWriteFailed: {\r\n id: 8103,\r\n source: WeatherDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Not able to write display Unit to PDP */\r\n WeatherPDPDisplayUnitWriteFailed: {\r\n id: 8104,\r\n source: WeatherDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Not able to localize Location */\r\n WeatherLocalizeLocationFailed: {\r\n id: 8105,\r\n source: WeatherDataConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nconst WeatherCardConnectorSourceFile = \"WeatherCard.connector.ts\";\r\nexport const WeatherCardAppErrors = {\r\n /** Failed to fetch local news */\r\n WeatherLocalNewsFetchError: {\r\n id: 8106,\r\n source: WeatherCardConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch autosuggest for locations */\r\n WeatherAutoSuggestFetchError: {\r\n id: 8107,\r\n source: WeatherCardConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** No valid Location set from User */\r\n WeatherLocationEmpty: {\r\n id: 8108,\r\n source: WeatherCardConnectorSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst SportsPdpServiceClientSourceFile = \"SportsPdpServiceClient.ts\";\r\nexport const SportsCardError = {\r\n /** Failed to fetch league sports pdp */\r\n SportsLeaguePdpFetchError: {\r\n id: 8110,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch league sports pdp */\r\n SportsLeaguePdpInvalidResponse: {\r\n id: 8111,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch players sports pdp */\r\n SportsPlayersPdpFetchError: {\r\n id: 8112,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch players sports pdp */\r\n SportsPlayersPdpInvalidResponse: {\r\n id: 8113,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch teams sports pdp */\r\n SportsTeamsPdpFetchError: {\r\n id: 8114,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch teams sports pdp */\r\n SportsTeamsPdpInvalidResponse: {\r\n id: 8115,\r\n source: SportsPdpServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get sports card config */\r\n SportsCardConfigFetchError: {\r\n id: 8116,\r\n source: \"SportsCardConfigReader.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get Team Data */\r\n SportsCardGetFavoriteTeamDataError: {\r\n id: 8117,\r\n source: \"SportsCard.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get Team Data */\r\n SportsCardGetPlayerBioError: {\r\n id: 8118,\r\n source: \"SportsCard.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetLeaguesGamesArrayError: {\r\n id: 8119,\r\n source: \"SportsCard.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetPdpDataFailure: {\r\n id: 8120,\r\n source: \"SportsCard.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetLeagueSeasonYearDataFailure: {\r\n id: 8121,\r\n source: \"SportsCardServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetLocalizedTeamNameDataFailure: {\r\n id: 8122,\r\n source: \"SportsCardServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetTeamDataFailure: {\r\n id: 8123,\r\n source: \"SportsCardServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n SportsCardGetLeagueDataFailure: {\r\n id: 8124,\r\n source: \"SportsCardServiceClient.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst MoneyCardConnectorFile = \"MoneyCard.connector.ts\";\r\nexport const MoneyCardError = {\r\n /** Failed to get quote summary for user */\r\n MoneyQuoteSummaryGetError: {\r\n id: 8130,\r\n source: MoneyCardConnectorFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get quote summaries */\r\n MoneyQuoteSummariesGetError: {\r\n id: 8131,\r\n source: MoneyCardConnectorFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get pdp data */\r\n MoneyPdpDataGetErrorFromService: {\r\n id: 8132,\r\n source: \"MoneyPdpServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get pdp data because of invalid response */\r\n MoneyPdpInvalidResponseFromService: {\r\n id: 8133,\r\n source: \"MoneyPdpServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get quote summary response for user from service client */\r\n MoneyQuoteSummaryGetErrorFromService: {\r\n id: 8134,\r\n source: \"MoneyQuotesServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get quote summary response for user from service client because of invalid response */\r\n MoneyQuoteSummaryInvalidResponseFromService: {\r\n id: 8135,\r\n source: \"MoneyQuotesServiceClient.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const TrendingNewsErrors = {\r\n /** Failed to fetch the trending news stories */\r\n DataFetchError: {\r\n id: 8140,\r\n source: \"TrendingNews.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Failed to fetch the backup data for trending news stories */\r\n BackupDataFetchError: {\r\n id: 8141,\r\n source: \"TrendingNews.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst ComplexContentPreviewSourceFile = \"ComplexContentPreview.connector.ts\";\r\nexport const ComplexContentPreviewErrors = {\r\n InitError: {\r\n id: 8150,\r\n source: ComplexContentPreviewSourceFile,\r\n severity,\r\n pb\r\n },\r\n LoadError: {\r\n id: 8151,\r\n source: ComplexContentPreviewSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nexport const GridSectionAppErrors = {\r\n /** Unable to generate river section cards */\r\n GridSectionCardGenerationError: {\r\n id: 8160,\r\n source: \"GridSection.tsx\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst MmxEntryPointFileName: string = \"MMXPage.connector.ts\";\r\n\r\nexport const MmxEntryPointAppErrors = {\r\n /**\r\n * MMX river is not able to load Error Page.\r\n */\r\n MmxErrorPage: {\r\n id: 8170,\r\n source: MmxEntryPointFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Error fetching the APP_ANON cookie on MMX page load\r\n */\r\n ErrorFetchingAppAnonCookie: {\r\n id: 8171,\r\n source: \"page.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst irisImageHotspotsFile = \"ImageHotspots.manager.ts\";\r\nexport const BackgroundImageAppErrors = {\r\n /** The Bing Image of the Day failed to load properly */\r\n BingIOTDFailedToLoad: {\r\n id: 8180,\r\n source: \"BingImageOfTheDayProvider.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Error when Iris fails to return Hotspots Data to the client. */\r\n FailedHotspotsDataDelivery: {\r\n id: 8181,\r\n source: irisImageHotspotsFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** Hotspots data that was returned failed to validate. */\r\n IncompleteHotspotsContract: {\r\n id: 8182,\r\n source: irisImageHotspotsFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nexport const SettingsDialogAppErrors = {\r\n /** Failed to get the saved layout preferences */\r\n ReadPreferencesFailed: {\r\n id: 8190,\r\n source: \"SettingsDialogEdgeNext.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch the ConfigData object from the client API */\r\n FetchNtpConfigDataFailed: {\r\n id: 8191,\r\n source: \"SettingsDialogEdgeNextBase.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const EdgePageSettingsAppErrors = {\r\n ServiceUiError: {\r\n id: 8192,\r\n source: \"EdgeSettingsProvider.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst MsnSettingMenuConnectorFileName = \"MsnSettingMenuConnector.connector.ts\";\r\n\r\nexport const MsnSettingsMenuAppErrors = {\r\n /** Failed to get feedback dialog connector */\r\n FailedToGetFeedbackDialogConnector: {\r\n id: 8193,\r\n source: MsnSettingMenuConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** Failed to get feedback data connector */\r\n FailedToGetFeedbackDataConnector: {\r\n id: 8194,\r\n source: MsnSettingMenuConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** The Msn settings menu failed to load valid config settings */\r\n MsnSettingsMenuFailedToFetchConfig: {\r\n id: 8195,\r\n source: MsnSettingMenuConnectorFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst ShowFeedConnectorFileName = \"ShowFeed.connector.ts\";\r\n\r\nexport const ShowFeedAppErrors = {\r\n MissingPageSettings: {\r\n id: 8199,\r\n source: ShowFeedConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n ExpectedDataMissing: {\r\n id: 8198,\r\n source: ShowFeedConnectorFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst InfopaneSourceFile = \"Infopane.connector.ts\";\r\nexport const InfopaneErrors = {\r\n InitializeError: {\r\n source: InfopaneSourceFile,\r\n id: 8201,\r\n severity,\r\n pb\r\n },\r\n InvalidConfig: {\r\n source: InfopaneSourceFile,\r\n id: 8202,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const FeedbackDialogAppErrors = {\r\n /** Failed to get feedback data connector */\r\n FailedToGetFeedbackDataConnector: {\r\n id: 8211,\r\n source: \"FeedbackDialog.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const FeedbackLinkAppErrors = {\r\n /** The Feedback link failed to load valid config settings */\r\n FeedbackLinkFailedToFetchConfig: {\r\n id: 8210,\r\n source: \"FeedbackLink.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Failed to get feedback dialog connector */\r\n FailedToGetFeedbackDialogConnector: {\r\n id: 8211,\r\n source: \"FeedbackLink.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Failed to get feedback data connector */\r\n FailedToGetFeedbackDataConnector: {\r\n id: 8212,\r\n source: \"FeedbackLink.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const OneFooterErrors = {\r\n InvalidConfig: {\r\n source: \"OneFooter.connector.ts\",\r\n id: 8220,\r\n severity,\r\n pb\r\n },\r\n /** Failed to get feedback data connector */\r\n FailedToGetFeedbackDataConnector: {\r\n id: 8221,\r\n source: \"OneFooter.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const PoweredByLegendAppErrors = {\r\n /** The PoweredBy legend failed to load expected config settings */\r\n PoweredByLegendInvalidConfig: {\r\n id: 8230,\r\n source: \"PoweredByLegend.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst TabbedInfopaneSourceFile = \"TabbedInfopane.connector.ts\";\r\nexport const TabbedInfopaneErrors = {\r\n InitializeError: {\r\n source: TabbedInfopaneSourceFile,\r\n id: 8250,\r\n severity,\r\n pb\r\n },\r\n InvalidConfig: {\r\n source: TabbedInfopaneSourceFile,\r\n id: 8251,\r\n severity,\r\n pb\r\n },\r\n ChildLoadError: {\r\n source: TabbedInfopaneSourceFile,\r\n id: 8252,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const MeControlAppErrors = {\r\n /** The SSO call failed to return valid SSO sign-in information. */\r\n SSOFailedError: {\r\n id: 8260,\r\n source: \"MeControl.tsx\",\r\n severity,\r\n pb\r\n },\r\n /** The Me Control failed to load */\r\n MeControlLoadFailedError: {\r\n id: 8261,\r\n source: \"MeControl.tsx\",\r\n severity: Severity.HighImpact,\r\n pb\r\n }\r\n};\r\n\r\nconst TabbedInfopaneTabPreviewSourceFile = \"TabbedInfopaneTabPreview.connector.ts\";\r\nexport const TabbedInfopaneTabPreviewErrors = {\r\n InitError: {\r\n source: TabbedInfopaneTabPreviewSourceFile,\r\n id: 8270,\r\n severity,\r\n pb\r\n },\r\n InvalidConfig: {\r\n source: TabbedInfopaneTabPreviewSourceFile,\r\n id: 8271,\r\n severity,\r\n pb\r\n },\r\n LoadError: {\r\n source: TabbedInfopaneTabPreviewSourceFile,\r\n id: 8272,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const HeaderNavigationLogoAppErrors = {\r\n MegaMenuDataError: {\r\n id: 8280,\r\n source: \"HeaderNavigationLogoConnector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst pageClicksTrackerFileName = \"pageClicksTracker.ts\";\r\nexport const PageClickTrackerErrors = {\r\n InvalidResponse: {\r\n id: 8290,\r\n severity: Severity.NoAlert,\r\n source: pageClicksTrackerFileName,\r\n pb\r\n },\r\n FetchFailure: {\r\n id: 8291,\r\n severity: Severity.NoAlert,\r\n source: pageClicksTrackerFileName,\r\n pb\r\n }\r\n};\r\n\r\nconst TargetingSystemSourceFile = \"TargetingSystem.ts\";\r\nexport const TargetingSystemAppErrors = {\r\n GeneralError: {\r\n id: 8310,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n },\r\n TopLevelDataMissing: {\r\n id: 8311,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n },\r\n TrackingDataUPSMissing: {\r\n id: 8312,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n },\r\n AppEnvironmentValuesMissing: {\r\n id: 8313,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n },\r\n CallingOneServiceFailed: {\r\n id: 8314,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n },\r\n CallingUPSServiceFailed: {\r\n id: 8315,\r\n source: TargetingSystemSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst CoachmarkSourceFile = \"Coachmark.connector.ts\";\r\nconst CoachmarkTSX = \"Coachmark.tsx\";\r\nexport const CoachmarkAppErrors = {\r\n GeneralError: {\r\n id: 8320,\r\n source: CoachmarkTSX,\r\n severity,\r\n pb\r\n },\r\n NotPlaceable: {\r\n id: 8321,\r\n source: CoachmarkTSX,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n NotFoundComponent: {\r\n id: 8322,\r\n source: CoachmarkSourceFile,\r\n severity,\r\n pb\r\n },\r\n CoachmarkDataConnectorUndefined: {\r\n id: 8323,\r\n source: CoachmarkSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst CoachmarkDataConnectorSourceFile = \"CoachmarkData.connector.ts\";\r\nconst CoachmarkPayloadSourceFile = \"CoachmarkPayload.ts\";\r\nconst IrisHandlerSourceFile = \"IrisHandler.ts\";\r\nexport const CoachmarkDataAppErrors = {\r\n InvalidCoachmarkMessage: {\r\n id: 8324,\r\n source: CoachmarkPayloadSourceFile,\r\n severity,\r\n pb\r\n },\r\n IrisDataConnectorUndefined: {\r\n id: 8325,\r\n source: IrisHandlerSourceFile,\r\n severity,\r\n pb\r\n },\r\n NoSurfaceFoundForCampaign: {\r\n id: 8326,\r\n source: IrisHandlerSourceFile,\r\n severity,\r\n pb\r\n },\r\n ErrorFoundForSurface: {\r\n id: 8327,\r\n source: IrisHandlerSourceFile,\r\n severity,\r\n pb\r\n },\r\n TelemetryInfoUndefined: {\r\n id: 8328,\r\n source: CoachmarkDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n EventTypeUndefined: {\r\n id: 8329,\r\n source: CoachmarkDataConnectorSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst SpotlightPreviewSourceFile = \"SpotlightPreview.connector.ts\";\r\n\r\nexport const SpotlightPreviewAppErrors = {\r\n ErrorWhileFetchingSpotlightPreviewCardInfo: {\r\n id: 8401,\r\n source: SpotlightPreviewSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n NoServiceContextMetadata: {\r\n id: 8402,\r\n source: SpotlightPreviewSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst SpotlightSourceFile = \"Spotlight.connector.ts\";\r\nexport const SpotlightErrors = {\r\n UnknownError: {\r\n id: 8500,\r\n source: SpotlightSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n ContentFetchError: {\r\n id: 8501,\r\n source: SpotlightSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const CardActionErrors = {\r\n /** Error catch in base CardAction experience container */\r\n CardActionBaseExperienceError: {\r\n id: 8600,\r\n source: \"CardAction.tsx\",\r\n severity,\r\n pb\r\n },\r\n /** Post action failed (Like/Dislike) */\r\n CardActionPostActionError: {\r\n id: 8601,\r\n source: \"CarActionServiceClient.tsx\",\r\n severity,\r\n pb\r\n },\r\n /** Delete action failed (Unlike/Undislike) */\r\n CardActionDeleteActionError: {\r\n id: 8602,\r\n source: \"CardActionServiceClient.tsx\",\r\n severity,\r\n pb\r\n },\r\n /** Get action failed (GetPublisherDetails) */\r\n CardActionGetActionError: {\r\n id: 8603,\r\n source: \"CardActionServiceClient.tsx\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst ContentRelatedSourceFile = \"ContentRelated.connector.ts\";\r\nexport const ContentRelatedErrors = {\r\n /**\r\n * Missing source Id error\r\n */\r\n MissingSourceIdError: {\r\n id: 8700,\r\n source: ContentRelatedSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Invalid sourceIdError\r\n */\r\n InvalidSourceIdError: {\r\n id: 8701,\r\n source: ContentRelatedSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Related contents feed fetch error\r\n */\r\n ContentRelatedFeedFetchError: {\r\n id: 8702,\r\n source: ContentRelatedSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst Cookies = \"Cookies.ts\";\r\nexport const CookieRelatedErrors = {\r\n SharedStateConnectorNull: {\r\n id: 8840,\r\n source: Cookies,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst CookieConsentBannerHelper = \"MsccCookieConsentHelper.ts\";\r\nexport const CookieConsentBannerHelperErrors = {\r\n FailedToParseStaticsUrls: {\r\n id: 8810,\r\n source: CookieConsentBannerHelper,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n ScriptsNotFound: {\r\n id: 8811,\r\n source: CookieConsentBannerHelper,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n StyleSheetsNotFound: {\r\n id: 8812,\r\n source: CookieConsentBannerHelper,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n FailedToMountScript: {\r\n id: 8813,\r\n source: CookieConsentBannerHelper,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n FailedToMountStyleSheet: {\r\n id: 8814,\r\n source: CookieConsentBannerHelper,\r\n severity: Severity.HighImpact,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents IFrame related errors */\r\nconst IFrameSourceFile = \"IFrame.tsx\";\r\nexport const IFrameErrors = {\r\n /** Message recieved by event listener not from expected origin */\r\n IFrameUnallowedOriginMessage: {\r\n id: 8820,\r\n source: IFrameSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const RightRailCarouselAppErrors = {\r\n NoChildrenExperienceFoundError: {\r\n id: 8830,\r\n source: \"RightRailCarousel.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const BreakingNewsErrors = {\r\n /** Error fetching Breaking News content */\r\n ContentFetchError: {\r\n id: 8901,\r\n source: \"BreakingNews.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Error fetching Blowout content */\r\n BlowoutDocumentFetchError: {\r\n id: 8902,\r\n source: \"BreakingNews.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const BlowoutErrors = {\r\n /** Error fetching Blowout content */\r\n ContentFetchError: {\r\n id: 8921,\r\n source: \"Blowout.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const OverlayErrors: { [name: string]: AppError } = {\r\n /** Error loading experience */\r\n LoadExperienceError: {\r\n id: 8941,\r\n source: \"Overlay.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const ViewsCommonAppErrors = {\r\n /** Invalid intra article component metadata passed. */\r\n InvalidIntraArticleDataError: {\r\n id: 9001,\r\n source: \"IntraArticleHelper.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch from data api. */\r\n DataFetchError: {\r\n id: 9002,\r\n source: \"ViewsServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Invalid content markup encountered. */\r\n InvalidDocumentContentError: {\r\n id: 9003,\r\n source: \"ViewsUtility.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load views paddle data from data api. */\r\n ViewsPaddleDataLoadError: {\r\n id: 9004,\r\n source: \"ViewsPaddle.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Error during app initialization for views page experience. */\r\n ViewsErrorPage: {\r\n id: 9005,\r\n source: \"page.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Error during mapping provider data for views content header experience */\r\n ProviderMapperError: {\r\n id: 9006,\r\n source: \"ViewContentHeader.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const LegacySharingToolbarAppErrors = {\r\n /** Failed to invoke legacy sharing toolbar. */\r\n LegacySharingToolbarInvokeError: {\r\n id: 9100,\r\n source: \"SharingHelper.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load sharing toolbar. */\r\n SharingToolbarLoadError: {\r\n id: 9101,\r\n source: \"LegacySharingToolbar.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Invalid source content id passed in. */\r\n InvalidContentIdError: {\r\n id: 9102,\r\n source: \"LegacySharingToolbar.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents ContentActionsToolbar experience related errors */\r\nconst ContentActionsToolbarConnectorSourceFile = \"ContentActionToolbar.connector.ts\";\r\nconst ContentActionsToolbarSourceFile = \"ContentActionToolbar.tsx\";\r\nconst ContentActionsToolbarServiceClientSourceFile = \"ContentActionToolbarServiceClient.tsx\";\r\nexport const ContentActionsToolbarAppErrors = {\r\n /** Failed to load sharing toolbar - 9120 */\r\n ContentActionsSharingToolbarLoadError: {\r\n id: 9120,\r\n source: ContentActionsToolbarConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Error fetching article data - 9121 */\r\n ContentActionsArticleDatafetchError: {\r\n id: 9121,\r\n source: ContentActionsToolbarConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Base Experience error - 9122 */\r\n ContentActionsBaseExperienceError: {\r\n id: 9122,\r\n source: ContentActionsToolbarSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Get content views action failed (getContentViewsRequest) - 9123 */\r\n ContentActionsGetDocumentDataError: {\r\n id: 9123,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Get content status action failed (getContentStatusRequest) - 9124 */\r\n ContentActionsGetContentStatusActionError: {\r\n id: 9124,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Delete action failed (Unlike/Undislike) - 9125 */\r\n ContentActionsDeleteActionError: {\r\n id: 9125,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Post action failed (Like/Dislike) - 9126 */\r\n ContentActionsPostActionError: {\r\n id: 9126,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Prime hybrid error loading the experience - 9127 */\r\n ContentActionsExperienceLoadError: {\r\n id: 9127,\r\n source: ContentActionsToolbarSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Missing vert/horiz placeholder to flip toolbar - 9128 */\r\n ContentActionsFlipToolbarError: {\r\n id: 9128,\r\n source: ContentActionsToolbarSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Failed fetching contentStatus - 9129 */\r\n ContentActionsContentStatusFetchError: {\r\n id: 9129,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** Failed fetching contentPreview - 9130 */\r\n ContentActionsContentPreviewFetchError: {\r\n id: 9130,\r\n source: ContentActionsToolbarServiceClientSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nexport const ContentSharingToolbarAppErrors = {\r\n ContentSharingToolbarInitializationError: {\r\n id: 9150,\r\n source: \"ContentSharingToolbar.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const ContentProviderAppErrors = {\r\n /** Invalid source article/gallery id passed in. */\r\n InvalidSourceIdError: {\r\n id: 9200,\r\n source: \"ContentProvider.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch provider details. */\r\n ProviderDetailsFetchError: {\r\n id: 9201,\r\n source: \"ContentProvider.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to fetch provider feed. */\r\n ProviderFeedFetchError: {\r\n id: 9202,\r\n source: \"ContentProvider.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Invalid layout template passed in. */\r\n InvalidLayoutTemplate: {\r\n id: 9203,\r\n source: \"ContentProvider.templates.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** ApplicationCache related messages */\r\nconst refreshHeadDataFile = \"Appcache/RefreshHeadData.ts\";\r\nconst edgeAppCacheHelperFile = \"Appcache/EdgeApplicationCacheHelper.ts\";\r\n\r\nexport const ApplicationCacheMessages = {\r\n FailedToFetchHeadData: {\r\n id: 9310,\r\n source: refreshHeadDataFile,\r\n severity,\r\n pb\r\n },\r\n CatastrophicFailedToFetchHeadData: {\r\n id: 9311,\r\n source: refreshHeadDataFile,\r\n severity,\r\n pb\r\n },\r\n StaleActivityIdEncountered: {\r\n id: 9312,\r\n source: refreshHeadDataFile,\r\n severity,\r\n pb\r\n },\r\n /**\r\n * The current DOM that is in AppCache doesn't match what should be getting served\r\n * to the user due to the existence of the ntps cookie that defines what the locale should be.\r\n * In this case, we must bypass AppCache to get the proper DOM from PCS.\r\n */\r\n LocaleMismatch: {\r\n id: 9313,\r\n source: edgeAppCacheHelperFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /**\r\n * Our checks determining we need to bypass appcache for the user are failing\r\n * to detect that the appcache refresh has succeeded. We've tried, for the current page view, to\r\n * bypass without any success.\r\n */\r\n RapidAppcacheForcedRefreshes: {\r\n id: 9314,\r\n source: edgeAppCacheHelperFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst ViewsGallerySourceFile = \"ViewsGallery.connector.ts\";\r\nexport const ViewsGalleryAppErrors = {\r\n /** Invalid gallery id passed. */\r\n InvalidGalleryIdError: {\r\n id: 10001,\r\n source: ViewsGallerySourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load gallery data. */\r\n GalleryDataLoadError: {\r\n id: 10010,\r\n source: ViewsGallerySourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load images. */\r\n GalleryImagesLoadError: {\r\n id: 10020,\r\n source: ViewsGallerySourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst SlideShowConnectorFile = \"SlideShow.connector.ts\";\r\nconst SlideShowCarouselFile = \"SlideShowCarousel.tsx\";\r\nexport const SlideShowAppErrors = {\r\n /** Invalid slideshow id passed. */\r\n InvalidSlideShowIdError: {\r\n id: 10100,\r\n source: SlideShowConnectorFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load slideshow data. */\r\n SlideShowDataLoadError: {\r\n id: 10110,\r\n source: SlideShowConnectorFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load images. */\r\n SlideShowImagesLoadError: {\r\n id: 10120,\r\n source: SlideShowConnectorFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to ads refresh. */\r\n SlideShowAdsRefreshError: {\r\n id: 10130,\r\n source: SlideShowCarouselFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load image. */\r\n SlideShowImageLoadFailed: {\r\n id: 10135,\r\n source: SlideShowCarouselFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const VideoListAppErrors = {\r\n /** Failed to load the video list data. */\r\n VideoListDataLoadError: {\r\n id: 11001,\r\n source: \"VideoList.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst VideoContentSourceFile: string = \"VideoContent.connector.ts\";\r\nexport const VideoContentAppErrors = {\r\n /** Failed to load the video content data. */\r\n InvalidResponseFromVideoContentResponseJson: {\r\n id: 11101,\r\n source: VideoContentSourceFile,\r\n severity\r\n },\r\n /** Failed to fetch the video content data from server. */\r\n ErrorWhileFetchingContentPreviewContent: {\r\n id: 11102,\r\n source: VideoContentSourceFile,\r\n severity\r\n }\r\n};\r\n\r\nconst ViewsArticleSourceFile = \"ViewsArticle.connector.ts\";\r\nexport const ViewsArticleAppErrors = {\r\n /** Invalid article id passed. */\r\n InvalidArticleIdError: {\r\n id: 12001,\r\n source: ViewsArticleSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load article data. */\r\n ArticleDataLoadError: {\r\n id: 12002,\r\n source: ViewsArticleSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load intra-article component. */\r\n IntraArticleComponentLoadError: {\r\n id: 12003,\r\n source: ViewsArticleSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to invoke inline gallery experience. */\r\n InlineGalleryInvokeError: {\r\n id: 12004,\r\n source: ViewsArticleSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const InterestsSearchAppErrors = {\r\n /** Received non 200 from OneService */\r\n ErrorResponseFromOneService: {\r\n id: 13000,\r\n source: \"InterestsSearchServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n /** Received a response from 200 but didn't have expected structure */\r\n ErrorResponseFromOneServiceIsInvalid: {\r\n id: 13001,\r\n source: \"InterestsSearchServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n /**\r\n * When building the XFeed URL for one of the suggestion items,\r\n * we weren't able to build a valid URL\r\n */\r\n InvalidUrlFoundForElement: {\r\n id: 13002,\r\n source: \"InterestsSearch.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /**\r\n * When building the XFeed URL for one of the suggestion items,\r\n * we weren't able to build a valid URL\r\n */\r\n SelectedItemNotFoundInSuggestions: {\r\n id: 13003,\r\n source: \"InterestsSearch.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n /**\r\n * When building the XFeed URL for one of the suggestion items,\r\n * we weren't able to build a valid URL\r\n */\r\n SelectedItemIsInvalid: {\r\n id: 13004,\r\n source: \"InterestsSearch.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst EdgeHeaderConnectorFileName: string = \"EdgeHeader.connector.ts\";\r\n\r\nexport const EdgeHeaderAppErrors = {\r\n /** The BingImageData Connector was not loaded */\r\n BingImageDataConnectorNotLoaded: {\r\n id: 8240,\r\n source: EdgeHeaderConnectorFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst MicrosoftNewsPageConnectorFileName: string = \"MicrosoftNewsPage.connector.ts\";\r\n\r\nexport const MicrosoftNewsPageAppErrors = {\r\n /** The BingImageData Connector was not loaded */\r\n BingImageDataConnectorNotLoaded: {\r\n id: 8241,\r\n source: MicrosoftNewsPageConnectorFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst InterestsConnectorFileName: string = \"Interests.connector.ts\";\r\nconst XfeedConnectorFileName: string = \"Xfeed.connector.ts\";\r\nexport const InterestsAppErrors = {\r\n /** We could not retrieve the list of Topics from OneService */\r\n InterestsRetrieveTopicsError: {\r\n id: 13100,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not retrieve the user's list of Followed Topics from OneService */\r\n InterestsRetrieveFollowedTopicsError: {\r\n id: 13101,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not retrieve the user's list of Muted Publishers from OneService */\r\n InterestsRetrieveMutedPublishersError: {\r\n id: 13102,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not UnMute a Muted Publisher */\r\n InterestsUnMutePublisherError: {\r\n id: 13103,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not follow a new interests topic */\r\n InterestsFollowTopicError: {\r\n id: 13104,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not unfollow an interests topic */\r\n InterestsUnfollowTopicError: {\r\n id: 13105,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** TopicState should not be undefined */\r\n InterestsTopicStateUndefined: {\r\n id: 13106,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** Topics should have rendered */\r\n InterestsShouldHaveRendered: {\r\n id: 13107,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** Could not retrieve a specific topic */\r\n InterestsRetrieveTopicError: {\r\n id: 13108,\r\n source: XfeedConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not retrieve the user's list of Saved Stories from OneService */\r\n InterestsRetrieveSavedStoriesError: {\r\n id: 13109,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** Saved stories config is invalid */\r\n InterestsSavedStoriesInvalidConfigError: {\r\n id: 13110,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not load saved stories children */\r\n InterestsSavedStoriesChildLoadError: {\r\n id: 13111,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** OneService response for saved stories had invalid json */\r\n InterestsSavedStoriesInvalidJsonError: {\r\n id: 13112,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** OneService response for saved stories had invalid list of response */\r\n InterestsSavedStoriesInvalidListError: {\r\n id: 13113,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not retrieve the user's list of Recommended Topics from OneService */\r\n InterestsRetrieveRecommendedTopicsError: {\r\n id: 13114,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** Topic Data Connector is not defined */\r\n UndefinedTopicDataConnector: {\r\n id: 13115,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not retrieve the user's list of Read Stories from OneService */\r\n InterestsRetrieveReadStoriesError: {\r\n id: 13116,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** Read stories config is invalid */\r\n InterestsReadStoriesInvalidConfigError: {\r\n id: 13117,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** We could not load Read stories children */\r\n InterestsReadStoriesChildLoadError: {\r\n id: 13118,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** OneService response for Read stories had invalid json */\r\n InterestsReadStoriesInvalidJsonError: {\r\n id: 13119,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** OneService response for Read stories had invalid list of response */\r\n InterestsReadStoriesInvalidListError: {\r\n id: 13120,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n },\r\n /** OneService failed resetting user default set of interests */\r\n FailedRestoringDefaultTopicsError: {\r\n id: 13121,\r\n source: InterestsConnectorFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** {ComponentConnector} base app errors */\r\nexport const ComponentConnectorAppErrors = {\r\n\r\n /** Duplicate child experience instance found */\r\n DuplicateChildInstanceFound: {\r\n id: 14000,\r\n source: \"ComponentConnector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load bundle */\r\n BundleLoadError: {\r\n id: 14001,\r\n source: \"ComponentConnector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** ChildConfigInfoList is null */\r\n ChildConfigInfoListNull: {\r\n id: 14002,\r\n source: \"ComponentConnector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Merge List start position must be greater than 0 */\r\n ListStartPositionInvalid: {\r\n id: 14003,\r\n source: \"ComponentConnector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to delay load child bundle */\r\n ChildDelayLoadError: {\r\n id: 14004,\r\n source: \"ComponentConnector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Milestone dependency failed to resolve and timeout triggered */\r\n ExperienceDependencyTimeout: {\r\n id: 14005,\r\n source: \"ComponentConnector.ts\",\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\n/** App errors for {ExperienceLoader} */\r\nexport const ExperienceLoaderAppErrors = {\r\n\r\n /** Logged when neither the config type nor config HREF was provided to the loader */\r\n InsufficientLoadArgs: {\r\n id: 14100,\r\n source: \"ExperienceLoader.ts\",\r\n severity: Severity.HighImpact,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents SearchHistoryCommon related App errors */\r\nconst SearchHistoryCommonSourceFile = \"SearchHistoryCommon.tsx\";\r\nexport const SearchHistoryCommonAppErrors = {\r\n /** Failed to parse search history response */\r\n ResponseParsingFailed: {\r\n id: 15000,\r\n source: SearchHistoryCommonSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Search history service call failed */\r\n ServiceCallFailed: {\r\n id: 15001,\r\n source: SearchHistoryCommonSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to render search history */\r\n RenderFailed: {\r\n id: 15002,\r\n source: SearchHistoryCommonSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Search history api response not received within configured time */\r\n Timeout: {\r\n id: 15003,\r\n source: SearchHistoryCommonSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Search history api call unauthorized */\r\n Unauthorized: {\r\n id: 15004,\r\n source: SearchHistoryCommonSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Search history api call forbidden */\r\n Forbidden: {\r\n id: 15005,\r\n source: SearchHistoryCommonSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Search history api not able to find recent search associated with this request */\r\n NotFound: {\r\n id: 15006,\r\n source: SearchHistoryCommonSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents a Search related error */\r\nexport const SearchError: AppError = {\r\n id: 15100,\r\n source: \"SearchBox.tsx\",\r\n severity: Severity.HighImpact,\r\n pb\r\n};\r\n\r\nconst PollsCardConnectorSourceFile = \"PollsCard.connector.ts\";\r\nexport const PollsCardAppErrors = {\r\n /**\r\n * Failed to fetch polls list\r\n */\r\n PollsListFetchError: {\r\n id: 18000,\r\n source: PollsCardConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Failed to fetch poll data\r\n */\r\n PollDataFetchError: {\r\n id: 18001,\r\n source: PollsCardConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * No data{questions} for poll\r\n */\r\n PollsCardInvalidPoll: {\r\n id: 18002,\r\n source: PollsCardConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Invalid Poll Quiz\r\n */\r\n PollsCardInvalidQuizPoll: {\r\n id: 18003,\r\n source: PollsCardConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * PollsVoteError\r\n */\r\n PollsCardVoteError: {\r\n id: 18004,\r\n source: PollsCardConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * PollsMapStateToPropsError\r\n */\r\n PollsCardMapStateToPropsError: {\r\n id: 18005,\r\n source: PollsCardConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * PollsUnknownError\r\n */\r\n PollsUnknownError: {\r\n id: 18006,\r\n source: PollsCardConnectorSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const EdgeNextAppErrors = {\r\n /**\r\n * Error during app initialization for EdgeNext page experience.\r\n */\r\n EdgeNextErrorPage: {\r\n id: 19000,\r\n source: \"page.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Error fetching the APP_ANON cookie on EdgeNext page load */\r\n ErrorFetchingAppAnonCookie: {\r\n id: 19001,\r\n source: \"page.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Tracking errors where we ended up showing the local ntp page.\r\n */\r\n EdgeNextLocalNTPPageShownSyntaxErrors: {\r\n id: 19002,\r\n source: \"page.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Tracking errors where we ended up showing the local ntp page.\r\n */\r\n EdgeNextLocalNTPPageShownBundleFailureErrors: {\r\n id: 19003,\r\n source: \"page.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Tracking errors where we ended up showing the local ntp page.\r\n */\r\n EdgeNextLocalNTPPageShownPageExceptionError: {\r\n id: 19004,\r\n source: \"page.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst AdRefreshSourceFile = \"AdsRefresh.ts\";\r\nconst ApnWrapperSourceFile = \"AppnexusWrapper.ts\";\r\nconst DisplayAdsAdsDetectionSourceFile = \"AdsDetection.ts\";\r\nconst DisplayAdsConnectorSourceFile = \"DisplayAds.connector.ts\";\r\nconst DisplayAdsManagerConnectorSourceFile = \"DisplayAdsManager.connector.ts\";\r\nconst NativeAdConnectorSourceFile = \"NativeAd.connector.ts\";\r\nconst OathWrapperSourceFile = \"OathAdsWrapper.ts\";\r\nconst PlacementManagerConnectorSourceFile = \"PlacementManager.connector.ts\";\r\nconst PlacementManagerCookieSyncSourceFile = \"PlacementManagerCookieSync.ts\";\r\nconst PlacementManagerCMSServiceSourceFile = \"PlacementManagerCMSService.ts\";\r\nconst NativeAdClientConnectorSourceFile = \"NativeAdClient.connector.ts\";\r\nconst PartnerScriptLoaderFile = \"PartnerScriptLoader.ts\";\r\nconst NativeAdBeaconSourceFile = \"Beacon.ts\";\r\n\r\nexport const MonetizationAppErrors = {\r\n /** Failed to load Placement Manager. */\r\n PlacementManagerLoadError: {\r\n id: 20000,\r\n source: NativeAdConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load arrangement position on native ad experience. */\r\n ArrangementPositionLoadError: {\r\n id: 20001,\r\n source: NativeAdConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get CMS Content. */\r\n GetCMSContentError: {\r\n id: 20002,\r\n source: PlacementManagerCMSServiceSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get SAM RTB Response. */\r\n GetSAMRTBResponseError: {\r\n id: 20003,\r\n source: PlacementManagerConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load MediaNet End Of Article Block. */\r\n MediaNetEOABError: {\r\n id: 20005,\r\n source: \"medianetNativeAdOnArticle.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** Invalid promo module config */\r\n InvalidPromoModuleConfig: {\r\n id: 20006,\r\n source: NativeAdConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to download cookie sync external script. */\r\n CookieSyncDownloadExternalScriptError: {\r\n id: 20007,\r\n source: PlacementManagerCookieSyncSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Missing cookie sync external script. */\r\n CookieSyncMissingExternalScriptUrl: {\r\n id: 20008,\r\n source: PlacementManagerCookieSyncSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Cookie sync timeout. */\r\n CookieSyncTimeout: {\r\n id: 20009,\r\n source: PlacementManagerCookieSyncSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Cookie sync partner script error */\r\n CookieSyncPartnerScriptError: {\r\n id: 20010,\r\n source: PlacementManagerCookieSyncSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Cookie pixel sync partner download error */\r\n CookieSyncPixelPartnerDownloadError: {\r\n id: 20011,\r\n source: PlacementManagerCookieSyncSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load cms or backfill native ad. */\r\n CMSOrBackfillNativeAdLoadError: {\r\n id: 20012,\r\n source: NativeAdConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Missing required property on placement manager config */\r\n MissingRequiredPropertyPlacementManagerConfig: {\r\n id: 20014,\r\n source: PlacementManagerConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Missing page type target scope. */\r\n NativeAdTargetScopeError: {\r\n id: 20016,\r\n source: NativeAdConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** River video ad partner error. */\r\n RiverVideoAdPartnerError: {\r\n id: 20017,\r\n source: PartnerScriptLoaderFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** JsTracker ad partner script load error. */\r\n JsTrackerPartnerScriptLoadError: {\r\n id: 20018,\r\n source: NativeAdBeaconSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Viglink load error. */\r\n ViglinkError: {\r\n id: 20019,\r\n source: PartnerScriptLoaderFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Missing topic id for stripe native ad */\r\n MissingTopicId: {\r\n id: 20020,\r\n source: NativeAdConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Topic id not found for stripe native ad */\r\n TopicIdNotFound: {\r\n id: 20021,\r\n source: NativeAdConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to get SAM RTB Response. This App error doesn't trigger alert */\r\n GetSAMRTBResponseErrorNoAlert: {\r\n id: 20022,\r\n source: PlacementManagerConnectorSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** Failed to load Oath JS */\r\n DisplayAdsOathLoadError: {\r\n id: 20500,\r\n source: OathWrapperSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to load AppNexus JS */\r\n DisplayAdsApnLoadError: {\r\n id: 20501,\r\n source: ApnWrapperSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** AppNexus Provider was empty */\r\n DisplayAdsApnEmptyProvider: {\r\n id: 20502,\r\n source: ApnWrapperSourceFile,\r\n severity: Severity.Alert\r\n },\r\n\r\n /** Ads Detection no initialized properly Provider was empty */\r\n DisplayAdsAdsDetectionNotInit: {\r\n id: 20503,\r\n source: DisplayAdsAdsDetectionSourceFile,\r\n severity: Severity.Alert,\r\n pb\r\n },\r\n\r\n /** Failed to load Moat JS */\r\n DisplayAdsMoatLoadError: {\r\n id: 20504,\r\n source: DisplayAdsManagerConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Display ad objects were not available for refresh */\r\n DisplayAdsNoAdObjects: {\r\n id: 20505,\r\n source: AdRefreshSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** There was a problem in encoding CMS provider ID from base 62 to 32 */\r\n DisplayAdsProviderIdEncode: {\r\n id: 20506,\r\n source: DisplayAdsConnectorSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const TaboolaRiverAppErrors = {\r\n /** Failed to fetch taboola river data. */\r\n TaboolaRiverFetchError: {\r\n id: 20100,\r\n source: \"TaboolaRiver.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst PCSPageHTMLFile = \"PCS-Page.cshtml\";\r\nexport const CoreLibAppErrors = {\r\n /** Deprecated composition layout config in use */\r\n DeprecatedCompositionLayoutUsed: {\r\n id: 20200,\r\n source: \"LayoutBase.inspector.ts\",\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** Deprecated composition layout config in use */\r\n InvalidColumnInGridConfig: {\r\n id: 20201,\r\n source: \"GridBase.inspector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Error during loading of page bundles.\r\n */\r\n ErrorLoadingBundle: {\r\n id: 20202,\r\n source: PCSPageHTMLFile,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n\r\n /**\r\n * Generic JS exceptions.\r\n */\r\n GenericJSException: {\r\n id: 20203,\r\n source: PCSPageHTMLFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents Authenticatedfetch related App errors */\r\nconst AuthenticatedFetchSourceFile = \"AuthenticatedFetch.ts\";\r\nexport const AuthenticatedFetchErrors = {\r\n EdgeChromiumAPIsNotAvailable: {\r\n id: 20300,\r\n source: AuthenticatedFetchSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n AcquireAccessTokenFailed: {\r\n id: 20301,\r\n source: AuthenticatedFetchSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n ErrorCodeReceived: {\r\n id: 20302,\r\n source: AuthenticatedFetchSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n CallFailed: {\r\n id: 20303,\r\n source: AuthenticatedFetchSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst resolverSourceFile = \"resolver.ts\";\r\nexport const ResolverAppErrors = {\r\n /**\r\n * IndexedDb write failed in resolver.\r\n */\r\n IndexedDbWriteFailed: {\r\n id: 22010,\r\n source: resolverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * IndexedDb read failed in resolver.\r\n */\r\n IndexedDbReadFailed: {\r\n id: 22011,\r\n source: resolverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Config Service Resolver fetch failed.\r\n */\r\n CrsFetchFailed: {\r\n id: 22012,\r\n source: resolverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Config Service Resolver was enabled but we still went to Assets to getConfig and merge configs at client (classic resolver).\r\n */\r\n ReceivedConfigFromCdnAsCrsFetchFailed: {\r\n id: 22013,\r\n source: resolverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Exception In GetConfig function.\r\n */\r\n GetConfigException: {\r\n id: 22014,\r\n source: resolverSourceFile,\r\n severity: Severity.HighImpact,\r\n pb\r\n },\r\n\r\n /**\r\n * IndexedDb bulk read failed in resolver.\r\n */\r\n IndexedDbBulkReadFailed: {\r\n id: 22015,\r\n source: resolverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * IndexedDb failed to remove cached config\r\n */\r\n IndexedDbFailedToRemoveCachedConfig: {\r\n id: 22016,\r\n source: resolverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * IndexedDb failed to clear all configs\r\n */\r\n IndexedDbFailedToClearAllCachedConfigs: {\r\n id: 22017,\r\n source: resolverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Render cache is purged due to changes in config\r\n */\r\n RenderCachePurgedDueToChangesInConfig: {\r\n id: 22018,\r\n source: resolverSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /**\r\n * Render cache failed purge even though config changes were detected.\r\n */\r\n FailedToPurgeRenderCache: {\r\n id: 22019,\r\n source: resolverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Failed to refresh config cache\r\n */\r\n RefreshConfigCacheFailed: {\r\n id: 22020,\r\n source: resolverSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Failed to initialize indexedDb\r\n */\r\n IndexedDbInitFailed: {\r\n id: 22021,\r\n source: resolverSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const HubAppErrors = {\r\n /**\r\n * Error during app initialization for hub page experience.\r\n */\r\n HubErrorPage: {\r\n id: 22100,\r\n source: \"page.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst EdgePageFileName: string = \"Edge/page.ts\";\r\n\r\n/** Edge App Type errors. */\r\nexport const EdgeAppErrors = {\r\n ErrorFetchingChildCookie: {\r\n id: 23000,\r\n source: EdgePageFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Error during app initialization for Edge page experience.\r\n */\r\n EdgeErrorPage: {\r\n id: 23001,\r\n source: EdgePageFileName,\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Error fetching the APP_ANON cookie on Edge page load\r\n */\r\n ErrorFetchingAppAnonCookie: {\r\n id: 23002,\r\n source: EdgePageFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Auth related app messages (errors|warnings) */\r\nexport const AuthenticationAppMessages = {\r\n AuthRefreshBlockedError: {\r\n id: 33000,\r\n source: \"\",\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /**\r\n * Error fetching the APP_ANON cookie\r\n */\r\n ErrorFetchingAppAnonCookie: {\r\n id: 33001,\r\n source: \"\",\r\n severity,\r\n pb\r\n },\r\n\r\n /**\r\n * Error during app initialization for Edge page experience.\r\n */\r\n EstablishSignedInState: {\r\n id: 1405,// need to mimic the prime one since telemetry cooking logic looks for this\r\n source: \"\",\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /**\r\n * Error during app initialization for migration consent\r\n */\r\n EstablishMigrationConsent: {\r\n id: 33010,\r\n source: \"EstablishMigrationConsent.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n MigrationConsentServiceClient: {\r\n id: 33011,\r\n source: \"MigrationConsentServiceClient.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const BingCardsAppErrors = {\r\n BingCardGetHotelAnswersError: {\r\n id: 24001,\r\n source: \"BingCardsServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n BingCardGetHotelErrorFromService: {\r\n id: 24002,\r\n source: \"BingCardsServiceClient.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n BingCardGetAnswersError: {\r\n id: 24003,\r\n source: \"BingCardsExperience.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n BingCardInvalidEntityType: {\r\n id: 24004,\r\n source: \"BingCardsExperience.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n BingCardErrorOut: {\r\n id: 24005,\r\n source: \"BingCardsExperience.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const BingAnswersAppErrors = {\r\n UnknownError: {\r\n id: 24101,\r\n source: \"BingAnswers.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n FailedToLoadData: {\r\n id: 24102,\r\n source: \"BingAnswers.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n NoCardsContentType: {\r\n id: 24103,\r\n source: \"BingAnswers.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n NoCardsRelated: {\r\n id: 24104,\r\n source: \"BingAnswers.connector.ts\",\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nconst BingShoppingShopCardServiceClientSourceFile =\r\n \"bing-shopping/ShopCardServiceClient.ts\";\r\n\r\nexport const BingShoppingShopCardError = {\r\n ShopCardServiceFetchError: {\r\n id: 24200,\r\n source: BingShoppingShopCardServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n ShopCardServiceFetchInvalidResponse: {\r\n id: 24201,\r\n source: BingShoppingShopCardServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n ShopCardServiceEmptyPersonalizedResponse: {\r\n id: 24202,\r\n source: BingShoppingShopCardServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n ShopCardServiceInvalidPersonalizedResponse: {\r\n id: 24203,\r\n source: BingShoppingShopCardServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n ShopCardServiceEmptyTrendingResponse: {\r\n id: 24204,\r\n source: BingShoppingShopCardServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n ShopCardServiceInvalidTrendingResponse: {\r\n id: 24205,\r\n source: BingShoppingShopCardServiceClientSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst BingShoppingLifestyleCardServiceClientSourceFile =\r\n \"bing-shopping-lifestyle-card/BingShoppingLifestyleCardServiceClient.ts\";\r\n\r\nconst BingShoppingLifestyleCardCdnServiceClientSourceFile =\r\n \"bing-shopping-lifestyle-card/BingShoppingLifestyleCardCdnServiceClient.ts\";\r\n\r\nconst BingShoppingLifestyleAutosuggestServiceClientSourceFile =\r\n \"bing-shopping-lifestyle-card/BingShoppingLifestyleAutosuggestServiceClient.ts\";\r\n\r\nconst BingShoppingLifestyleConnectorSourceFile =\r\n \"bing-shopping-lifestyle-card/BingShoppingLifestyleCard.connector.ts\";\r\nexport const BingShoppingLifestyleCardError = {\r\n // Lifestyle Shopcard service Errors\r\n LifestyleShopCardServiceFetchError: {\r\n id: 24300,\r\n source: BingShoppingLifestyleCardServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n LifestyleShopCardServiceFetchInvalidResponse: {\r\n id: 24301,\r\n source: BingShoppingLifestyleCardServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n LifestyleShopCardServiceEmptyResponse: {\r\n id: 24302,\r\n source: BingShoppingLifestyleCardServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n LifestyleShopCardServiceInvalidResponse: {\r\n id: 24303,\r\n source: BingShoppingLifestyleCardServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n // Lifestyle Shopcard Cdn service Errors\r\n LifestyleShopCardCdnServiceFetchError: {\r\n id: 24304,\r\n source: BingShoppingLifestyleCardCdnServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n LifestyleShopCardCdnServiceFetchInvalidResponse: {\r\n id: 24305,\r\n source: BingShoppingLifestyleCardCdnServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n LifestyleShopCardCdnServiceInvalidResponse: {\r\n id: 24306,\r\n source: BingShoppingLifestyleCardCdnServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n // Lifestyle Autosuggest service Errors\r\n LifestyleShopAutosuggestServiceFetchError: {\r\n id: 24310,\r\n source: BingShoppingLifestyleAutosuggestServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n LifestyleShopAutosuggestServiceFetchInvalidResponse: {\r\n id: 24311,\r\n source: BingShoppingLifestyleAutosuggestServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n LifestyleShopAutosuggestServiceEmptyResponse: {\r\n id: 24312,\r\n source: BingShoppingLifestyleAutosuggestServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n LifestyleShopAutosuggestServiceInvalidResponse: {\r\n id: 24313,\r\n source: BingShoppingLifestyleAutosuggestServiceClientSourceFile,\r\n severity,\r\n pb\r\n },\r\n LifestyleShopAutosuggestInvalidSuggestionUrl: {\r\n id: 24314,\r\n source: BingShoppingLifestyleConnectorSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const PageSettingsDataConnectorAppErrors = {\r\n PageSettingsGetInitialState: {\r\n id: 26001,\r\n source: \"PageSettingsData.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst MicrosoftNewsEntryPointFileName: string = \"MicrosoftNews.connector.ts\";\r\nexport const MicrosoftNewsEntryPointAppErrors = {\r\n /**\r\n * Error during app initialization for MicrosoftNews page experience.\r\n */\r\n MicrosoftNewsErrorPage: {\r\n id: 27000,\r\n source: MicrosoftNewsEntryPointFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const NavigationDataConnectorAppErrors = {\r\n /**\r\n * Error while trying to fetch the Navigation Items\r\n */\r\n NavigationDataGetNavigationItems: {\r\n id: 28000,\r\n source: \"NavigationData.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n NavigationDataIndexedDbInitializationFailed: {\r\n id: 28001,\r\n source: \"NavigationData.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n NavigationDataIndexedDbWriteFailed: {\r\n id: 28002,\r\n source: \"NavigationData.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n NavigationDataIndexedDbBulkReadFailed: {\r\n id: 28003,\r\n source: \"NavigationData.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nexport const CategoryDataConnectorAppErrors = {\r\n /**\r\n * Error while to get the category details\r\n */\r\n CategoryDataGetCategoryDetail: {\r\n id: 28100,\r\n source: \"CategoryData.connector.ts\",\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n CategoryDataIndexedDbInitializationFailed: {\r\n id: 28101,\r\n source: \"CategoryData.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n CategoryDataIndexedDbWriteFailed: {\r\n id: 28102,\r\n source: \"CategoryData.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n CategoryDataIndexedDbBulkReadFailed: {\r\n id: 28103,\r\n source: \"CategoryData.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/**\r\n * App reporting messages related to OneService Content Data Connector\r\n */\r\nexport const OneServiceContentDataConnector = {\r\n /**\r\n * Message sent when a feature tries to update\r\n * the cache bypass value but the connector was not initialized\r\n * for the page\r\n */\r\n FailedToUpdateBypassValueConnectorNotInitialized: {\r\n id: 28200,\r\n source: \"OneServiceContentHelper.ts\",\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /**\r\n * Message sent when a feature tries to update\r\n * the cache bypass value but the connector was not initialized\r\n * for the page\r\n */\r\n FailedToGetBypassValueConnectorNotInitialized: {\r\n id: 28201,\r\n source: \"OneServiceContentHelper.ts\",\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\nexport const NotificationBellErrors = {\r\n /** Failed to fetch the notification bell data content */\r\n DataFetchError: {\r\n id: 28400,\r\n source: \"NotificationBell.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n JsonParseError: {\r\n id: 28401,\r\n source: \"LocalStorageSettings.ts\",\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\n/**\r\n * App reporting messages related to Stripe Experience\r\n */\r\nexport const StripeAppErrors = {\r\n InvalidConfig: {\r\n id: 28300,\r\n source: \"Stripe.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/**\r\n * App reporting messages related to StripeView Experience\r\n */\r\nexport const StripeViewAppErrors = {\r\n InvalidConfig: {\r\n id: 28600,\r\n source: \"StripeView.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n ChildLoadError: {\r\n id: 28601,\r\n source: \"StripeView.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents RecommendedSearch related App errors */\r\nconst RecommendedSearchSourceFile = \"RecommendedSearch.connector.ts\";\r\nexport const RecommendedSearchErrors = {\r\n /** Failed to parse recommended search response */\r\n ResponseParsingFailed: {\r\n id: 15200,\r\n source: RecommendedSearchSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** recommended search service returned invalid Json response */\r\n InvalidJsonResponse: {\r\n id: 15201,\r\n source: RecommendedSearchSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** recommended search service call failed */\r\n ServiceCallFailed: {\r\n id: 15202,\r\n source: RecommendedSearchSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Failed to render recommended searches */\r\n RenderFailed: {\r\n id: 15203,\r\n source: RecommendedSearchSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** recommended search api response not received within configured time */\r\n Timeout: {\r\n id: 15204,\r\n source: RecommendedSearchSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents Layout Preference Data Connector related App errors */\r\nconst LayoutPreferenceDataSourceFile = \"LayoutPreferenceData.connector.ts\";\r\nexport const LayoutPreferenceDataErrors = {\r\n /** Failed to retrieve Layout Preference Data */\r\n LayoutPreferenceDataGetFailed: {\r\n id: 28500,\r\n source: LayoutPreferenceDataSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents Sentiment Line Chart Connector related app errors */\r\nconst SentimentLineChartSourceFile = \"SentimentLineChart.connector.ts\";\r\nexport const SentimentLineChartErrors = {\r\n ContentFetchError: {\r\n id: 28700,\r\n source: SentimentLineChartSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents Sentiment Result Card Connector related app errors */\r\nconst SentimentResultCardSourceFile = \"SentimentResultCard.connector.ts\";\r\nexport const SentimentResultCardErrors = {\r\n ContentFetchError: {\r\n id: 28710,\r\n source: SentimentResultCardSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents Sentiment Map Connector related app errors */\r\nconst SentimentMapSourceFile = \"SentimentMap.connector.ts\";\r\nexport const SentimentMapErrors = {\r\n ContentFetchError: {\r\n id: 28720,\r\n source: SentimentMapSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents Election Results Card Connector related app errors */\r\nconst ElectionResultsCardFile = \"ElectionResultsCard.connector.ts\";\r\nexport const ElectionResultsCardErrors = {\r\n ContentFetchError: {\r\n id: 28730,\r\n source: ElectionResultsCardFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents Sentiment Bar chart Connector related app errors */\r\nconst SentimentBarChartSourceFile = \"SentimentBarChart.connector.ts\";\r\nexport const SentimentBarChartErrors = {\r\n ContentFetchError: {\r\n id: 28740,\r\n source: SentimentBarChartSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Elction Result Map connector App errors */\r\nconst ElectionResultMapConnectorSourceFile = \"ElectionResultMap.connector.ts\";\r\nexport const ElectionResultMapConnectorErrors = {\r\n UnknownError: {\r\n id: 28750,\r\n source: ElectionResultMapConnectorSourceFile,\r\n severity\r\n },\r\n\r\n ContentFetchError: {\r\n id: 28751,\r\n source: ElectionResultMapConnectorSourceFile,\r\n severity\r\n }\r\n};\r\n\r\n/** Elction Result Map Inspector App errors */\r\nconst ElectionResultMapInspectorSourceFile = \"ElectionResultMap.inspector.ts\";\r\nexport const ElectionResultMapInspectorErrors = {\r\n EmptyResultSummaryError: {\r\n id: 28752,\r\n source: ElectionResultMapInspectorSourceFile,\r\n severity\r\n }\r\n};\r\n/** Elction Result Map App errors */\r\nconst ElectionResultMapSourceFile = \"ElectionResultMap.tsx\";\r\nexport const ElectionResultMapErrors = {\r\n FetchAndUpdateElectionDataError: {\r\n id: 28753,\r\n source: ElectionResultMapSourceFile,\r\n severity\r\n }\r\n};\r\n\r\n/** Election Editor's Note App errors */\r\nexport const ElectionEditorsNoteErrors = {\r\n\r\n ContentFetchError: {\r\n id: 28760,\r\n source: \"ElectionEditorsNote.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents Election Delegate Counter related app errors */\r\nexport const ElectionDelegateCounterErrors = {\r\n ContentFetchError: {\r\n id: 28770,\r\n source: \"ElectionDelegateCounter.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/**\r\n * App reporting messages related to Partner Widget Experience\r\n */\r\nexport const PartnerWidgetAppErrors = {\r\n /** default breakpoint settings missing */\r\n DefaultBreakpointSettingsMissing: {\r\n id: 28801,\r\n source: \"PartnerWidget.connector.ts\",\r\n severity,\r\n pb\r\n },\r\n\r\n /** non whitelisted source url */\r\n NonWhitelistedSourceUrl: {\r\n id: 28802,\r\n source: \"PartnerWidget.connector.ts\",\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents RecommendedSearch related App errors */\r\nconst RecommendedTopicsSourceFile = \"RecommendedTopics.connector.ts\";\r\nexport const RecommendedTopicsErrors = {\r\n /** Failed to connect to the Topics Data Connector */\r\n TopicsDataConnectorFailed: {\r\n id: 28901,\r\n source: RecommendedTopicsSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Topic Clicked was null */\r\n InvalidTopicClick: {\r\n id: 28902,\r\n source: RecommendedTopicsSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst webWorkerSource = \"Web worker\";\r\nconst webWorkerUtility = \"WebWorkerUtility.ts\";\r\nexport const WebWorkerErrors = {\r\n /** Web worker script load error (404 response) */\r\n FileNotFound: {\r\n id: 29000,\r\n source: webWorkerUtility,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Web worker runtime error, fired by web worker on unhandled exceptions */\r\n RuntimeError: {\r\n id: 29001,\r\n source: webWorkerSource,\r\n severity,\r\n pb\r\n },\r\n\r\n /** Web worker message timeout */\r\n MessageTimeout: {\r\n id: 29002,\r\n source: webWorkerUtility,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n /** Web worker handled errors. These are the errors received as messages from web worker */\r\n HandledError: {\r\n id: 29003,\r\n source: webWorkerSource,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst EntryPointConnector = \"EntryPointConnector\";\r\nexport const EntryPointConnectorEvents = {\r\n /**\r\n * Indicates that for some reason the page never received all the perf markers it was waiting for\r\n * resulting in the timeout logic kicking in.\r\n */\r\n WaitForAllPerfMarkersTimeoutInvoked: {\r\n id: 29100,\r\n source: EntryPointConnector,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};\r\n\r\nconst FirstPartyEntryPointFileName: string = \"FirstParty.connector.ts\";\r\nexport const FirstPartyEntryPointAppErrors = {\r\n /**\r\n * Error during app initialization for FirstParty page experience.\r\n */\r\n FirstPartyErrorPage: {\r\n id: 29200,\r\n source: FirstPartyEntryPointFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\nconst irisArcCallerFileName = \"Iris.arcCaller.ts\";\r\nconst irisArcParserFileName = \"Iris.arcParser.ts\";\r\nconst irisMasterFileName = \"Iris.master.ts\";\r\nexport const IrisErrors = {\r\n /** Generic Unknown related to the Iris system. Investigate. */\r\n IrisUnknown: {\r\n id: 35000,\r\n source: \"Iris\",\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n /** The query parameters presented to the arc caller were found to be invalid. */\r\n InvalidQParams: {\r\n id: 35001,\r\n source: irisArcCallerFileName,\r\n severity,\r\n pb\r\n },\r\n ArcCallFailed: {\r\n id: 35002,\r\n source: irisArcCallerFileName,\r\n severity,\r\n pb\r\n },\r\n ArcResponseNotOk: {\r\n id: 35003,\r\n source: irisArcCallerFileName,\r\n severity,\r\n pb\r\n },\r\n ArcResponseUnparsable: {\r\n id: 35004,\r\n source: irisArcCallerFileName,\r\n severity,\r\n pb\r\n },\r\n MissingAppEnv: {\r\n id: 35005,\r\n source: irisArcCallerFileName,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n UnknownIrisErrorFound: {\r\n id: 35006,\r\n source: irisArcParserFileName,\r\n severity,\r\n pb\r\n },\r\n TimeoutIrisErrorFound: {\r\n id: 35007,\r\n source: irisArcParserFileName,\r\n severity,\r\n pb\r\n },\r\n TemplateIrisErrorFound: {\r\n id: 35008,\r\n source: irisArcParserFileName,\r\n severity,\r\n pb\r\n },\r\n ClientErrorIrisErrorFound: {\r\n id: 35009,\r\n source: irisArcParserFileName,\r\n severity,\r\n pb\r\n },\r\n DSourceIrisErrorFound: {\r\n id: 35010,\r\n source: irisArcParserFileName,\r\n severity,\r\n pb\r\n },\r\n ActionCallFailure: {\r\n id: 35011,\r\n source: irisArcCallerFileName,\r\n severity,\r\n pb\r\n },\r\n ActionFetchFailure: {\r\n id: 35012,\r\n source: irisArcCallerFileName,\r\n severity,\r\n pb\r\n },\r\n ActionResponseFailure: {\r\n id: 35013,\r\n source: irisArcCallerFileName,\r\n severity,\r\n pb\r\n },\r\n UncaughtErrorDetected: {\r\n id: 35014,\r\n source: irisMasterFileName,\r\n severity,\r\n pb\r\n },\r\n UnconvertableCreative: {\r\n id: 35015,\r\n source: irisMasterFileName,\r\n severity,\r\n pb\r\n },\r\n InvalidResponseFormat: {\r\n id: 35016,\r\n source: irisMasterFileName,\r\n severity,\r\n pb\r\n },\r\n AbortErrorDiscovered: {\r\n id: 35017,\r\n source: irisMasterFileName,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n UnparsableSingleResponseJSON: {\r\n id: 35018,\r\n source: irisMasterFileName,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents Iris data connector related App errors */\r\nconst IrisDataConnectorSourceFile = \"IrisData.connector.ts\";\r\nconst SubscriberValidatorSourceFile = \"SubscriberValidator.ts\";\r\nexport const IrisDataConnectorErrors = {\r\n SubscriberNotFound: {\r\n id: 35117,\r\n source: SubscriberValidatorSourceFile,\r\n severity,\r\n pb\r\n },\r\n CreativeCountNegativeOrZero: {\r\n id: 35118,\r\n source: IrisDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n ErrorFetchingSurfaceInfo: {\r\n id: 35119,\r\n source: IrisDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n ErrorFoundForSurface: {\r\n id: 35120,\r\n source: IrisDataConnectorSourceFile,\r\n severity,\r\n pb\r\n },\r\n SubscriberNotFoundInIrisPlacementDictionary: {\r\n id: 35121,\r\n source: IrisDataConnectorSourceFile,\r\n severity,\r\n pb\r\n }\r\n};\r\n\r\n/** Represents AccessTokens related App errors */\r\nconst AccessTokensSourceFile = \"AccessTokens.ts\";\r\nconst PivotContentErrorPlaceholderFile = \"AadErrorPlaceholder.tsx\";\r\nexport const AccessTokensErrors = {\r\n EdgeChromiumAPIsNotAvailable: {\r\n id: 35200,\r\n source: AccessTokensSourceFile,\r\n severity,\r\n pb\r\n },\r\n\r\n AcquireAccessTokenFailed: {\r\n id: 35201,\r\n source: AccessTokensSourceFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n },\r\n\r\n AcquireAccessTokenFailedForPivotContent: {\r\n id: 35202,\r\n source: PivotContentErrorPlaceholderFile,\r\n severity: Severity.NoAlert,\r\n pb\r\n }\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Attempts to parse a given string to a JSON object\r\n * @param {string} jsonString - The string to parse.\r\n * @returns {any} - the parsed object if successful, or null otherwise.\r\n */\r\nexport function tryParseJson(jsonString: string): any {\r\n try {\r\n return JSON.parse(jsonString);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** Attempts to parse the given value as a integer and if failed will return the defaultValue.\r\n * @param {string} value - The value to parse.\r\n * @param {number} defaultValue - The default value to return if parsing fails\r\n * @returns {number} the parsed value if it was a valid number or otherwise the default value if specified.\r\n */\r\nexport function tryParseInt(value: string, defaultValue: number): number {\r\n let n = parseInt(value);\r\n return isNaN(n) ? defaultValue : n;\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { BrowserConsoleAppender } from \"clientcore-infrastructure-analytics/appenders/BrowserConsoleAppender\";\r\nimport { ILoggingService } from \"clientcore-infrastructure-analytics/ILoggingService\";\r\nimport { LogLevel } from \"clientcore-infrastructure-analytics/models/LogLevel\";\r\nimport { LoggingService } from \"clientcore-infrastructure-analytics/LoggingService\";\r\nimport { NodeConsoleAppender } from \"clientcore-infrastructure-analytics/appenders/NodeConsoleAppender\";\r\nimport { RuntimeEnvironment } from \"clientcore-infrastructure-analytics/RuntimeEnvironment\";\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\n\r\n/** The Logger class */\r\nexport class Logger {\r\n /** A default instance of the Logger class. */\r\n public static readonly defaultInstance: Logger = new Logger();\r\n\r\n /** Backing field for the isDebug function */\r\n private isDebugEnabled: boolean;\r\n\r\n /** The common logger for the application. The logging level for this is updated in initialize */\r\n private logger: ILoggingService;\r\n\r\n /** Backing field to hold reference to the window object */\r\n private windowObj?: Window;\r\n\r\n /**\r\n * The constructor\r\n */\r\n private constructor() {\r\n if (canUseDOM()) {\r\n this.setupBrowserEnvironment(window);\r\n\r\n if (this.isDebugEnabled) {\r\n // @ts-ignore\r\n window.webpackRequire = __webpack_require__;\r\n }\r\n } else {\r\n this.setupNodeEnvironment();\r\n }\r\n }\r\n\r\n /**\r\n * Setup client side logging environment - this sets / overrides the Window obj\r\n * @param windowObj - The Window obj to use\r\n */\r\n public setupBrowserEnvironment(windowObj: Window): void {\r\n this.logger = LoggingService.getInstance(\"ExperienceLogger\", LogLevel.Info, RuntimeEnvironment.Browser);\r\n\r\n this.windowObj = windowObj;\r\n\r\n // Once we have a WindowObj, we can determine if debug mode is enabled\r\n this.isDebugEnabled = ((this.getQueryParameterByName(windowObj.location.href, \"debug\") || \"\").toLowerCase() in { \"1\": 1, \"true\": 1 });\r\n\r\n this.setupLogLevel();\r\n }\r\n\r\n /**\r\n * Setup server side logging environment\r\n */\r\n public setupNodeEnvironment(): void {\r\n this.logger = LoggingService.getInstance(\"ExperienceLogger\", LogLevel.Info, RuntimeEnvironment.NodeJs);\r\n this.isDebugEnabled = false; // isDebugEnabled should be set explictly using the setDebug method\r\n this.setupLogLevel();\r\n }\r\n\r\n /**\r\n * Returns the logging service\r\n * @returns {ILoggingService}\r\n */\r\n public getLoggingService(): ILoggingService {\r\n return this.logger;\r\n }\r\n\r\n /**\r\n * Checks whether we're running in debug mode.\r\n * @returns True when either debug=1 or debug=true is present as a query param, otherwise false.\r\n */\r\n public isDebug(): boolean {\r\n return this.isDebugEnabled;\r\n }\r\n\r\n /**\r\n * Override the isDebug setting. Useful when server side rendering.\r\n */\r\n public setDebug(isDebug: boolean): void {\r\n this.isDebugEnabled = isDebug;\r\n this.setupLogLevel();\r\n }\r\n\r\n /**\r\n * Log console message.\r\n * Note that these are not output to the console unless you're in debug mode.\r\n * @param message - Message to log.\r\n */\r\n public log(message: string): void {\r\n if (this.isDebug()) {\r\n if (!canUseDOM()) {\r\n // currently the logger is incredibly verbose when printing on the server side.\r\n // For now just directly print to console.\r\n // Work Item to address this: http://osgvsowi/24861651\r\n console.log(\"logger.info:\", message);\r\n } else {\r\n this.logger.info(message);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Log error message.\r\n * @param message - Message to log\r\n */\r\n public logError(message: string): void {\r\n this.logger.error(message);\r\n }\r\n\r\n /**\r\n * Lazy log console message. Use this when the message being constructed is complex or expensive so that it's only evaluated if needed.\r\n * Note that the callback is not invoked and the message is not output unless you're in debug mode.\r\n * @param getMessage - The function to call to get message to log\r\n */\r\n public logCallback(getMessage: () => string): void {\r\n this.logger.infoCallback(getMessage);\r\n }\r\n\r\n /**\r\n * Log the object to the console.\r\n * Note that these are not output to the console unless you're in debug mode.\r\n * @param message - Array of messages to log\r\n */\r\n public logObjects(...message: any[]): void {\r\n if (this.isDebug()) {\r\n if (canUseDOM() && this.windowObj) {\r\n this.windowObj.console.log(...message);\r\n } else {\r\n console.log(\"logger.logObjects:\", ...message);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Set logger log level.\r\n */\r\n private setupLogLevel(): void {\r\n // Note that we need to set the level at the root logger level or else the callback versions of the logging\r\n // methods will still be invoked to disseminate the message to the appenders.\r\n this.logger.setLevel(this.isDebug() ? LogLevel.Info : LogLevel.Error);\r\n this.setupAppenders();\r\n }\r\n\r\n /**\r\n * Add relevant appenders to the logger depending.\r\n */\r\n private setupAppenders(): void {\r\n this.logger.removeAllAppenders();\r\n if (canUseDOM()) {\r\n this.logger.addAppender(new BrowserConsoleAppender(this.logger.getLevel()));\r\n } else {\r\n this.logger.addAppender(new NodeConsoleAppender(this.logger.getLevel()));\r\n }\r\n }\r\n\r\n /**\r\n * Utility method to extract query string param in url.\r\n * @param name - Query param name\r\n * @returns Query param value\r\n */\r\n private getQueryParameterByName(locationHref: string, name: string): string {\r\n\r\n const nameRegEx = name.replace(/[\\[\\]]/g, \"\\\\$&\");\r\n const regex: any = new RegExp(\"[?&]\" + nameRegEx + \"(=([^&#]*)|&|#|$)\");\r\n\r\n const queryNameValueMatches: any = regex.exec(locationHref);\r\n if (!queryNameValueMatches) {\r\n return null;\r\n }\r\n\r\n // the second group would contain the value of the param\r\n let queryValue = queryNameValueMatches[2];\r\n\r\n return decodeURIComponent(queryValue.replace(/\\+/g, \" \")) || \"\";\r\n }\r\n}\r\n\r\nexport const logger = Logger.defaultInstance;","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { toNumber as _toNumber, isString } from \"lodash-es\";\r\n\r\nexport type KeyValuePair = { key: K, value: V };\r\nexport type KeyValueArray = KeyValuePair[];\r\n\r\nexport namespace Utility {\r\n /**\r\n * Check if given value is not null. Returns true when not null, otherwise false.\r\n *\r\n * @export\r\n * @param {any} value - Value to check for not null\r\n * @return {boolean}\r\n */\r\n export function isNotNullOrUndefined(value: any): boolean {\r\n return typeof value !== \"undefined\" && value !== null;\r\n }\r\n\r\n export interface IHashable {\r\n /**\r\n * This function will return the string representation of the complex object\r\n * @type {function}\r\n */\r\n toString(): string;\r\n }\r\n\r\n /**\r\n * Check if given value is defined. Returns true when defined, otherwise false.\r\n *\r\n * @export\r\n * @param {any} value - Value to check for defined\r\n * @return {boolean}\r\n */\r\n export function isDefined(value: any): boolean {\r\n return (typeof value !== \"undefined\");\r\n }\r\n\r\n /**\r\n * Check if a given value is a valid key value pair\r\n *\r\n * @export\r\n * @param potentialKeyValuePair\r\n * @return {boolean}\r\n */\r\n export function isKeyValuePair(potentialKeyValuePair: { key: K, value: V },\r\n isKey: (key: K) => boolean,\r\n isValue: (value: V) => boolean ): boolean {\r\n return Utility.isNonNullObject(potentialKeyValuePair)\r\n && isKey(potentialKeyValuePair.key)\r\n && isValue(potentialKeyValuePair.value);\r\n }\r\n\r\n /**\r\n * Check if given value is a non null object. Returns true when value is non null , otherwise false.\r\n *\r\n * @export\r\n * @param {any} value - Value to check for non null\r\n * @return {boolean}\r\n */\r\n export function isNonNullObject(value: any): boolean {\r\n return value && typeof value === \"object\";\r\n }\r\n\r\n /**\r\n * Check if given value is not null. Returns true when not null, otherwise false.\r\n *\r\n * @export\r\n * @param {any} value - Value to check for not null\r\n * @return {boolean}\r\n */\r\n export function isNotNull(value: any): boolean {\r\n return value !== null;\r\n }\r\n\r\n /**\r\n * Check if given value is a a non-null or non-empty string. Returns true when it is, otherwise false.\r\n *\r\n * @export\r\n * @param {string} value - Value to check for string\r\n * @return {boolean}\r\n */\r\n export function isNullOrWhiteSpace(value: string): boolean {\r\n return !isString(value) || value.trim() === \"\";\r\n }\r\n\r\n /**\r\n * Converts string to number\r\n *\r\n * @export\r\n * @param {string} value - string to convert to a number\r\n * @param {number} defaultValue - number to return if there is an error\r\n * @return {number}\r\n */\r\n export function toNumber(value: string, defaultValue: number = -1): number {\r\n if (!value) {\r\n return defaultValue;\r\n }\r\n\r\n const result = _toNumber(value);\r\n if (!isNaN(result)) {\r\n return result;\r\n } else {\r\n return defaultValue;\r\n }\r\n }\r\n\r\n /**\r\n * Check if given value is an array with content in it.\r\n * Returns true when value is an array with content, otherwise false.\r\n *\r\n * @export\r\n * @param {any[]} value - Value to check for array with content\r\n * @return {boolean}\r\n */\r\n export function arrayHasData(value: any[]): boolean {\r\n if (isNotNullOrUndefined(value)) {\r\n return ((value.constructor === Array) && (value.length > 0));\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check if given value is a string with content in it.\r\n * Returns true when value is a string with content, otherwise false.\r\n *\r\n * @export\r\n * @param {string} value - Value to check for string with content\r\n * @return {boolean}\r\n */\r\n export function stringHasData(value: string): boolean {\r\n return (isString(value) && (value.trim().length > 0));\r\n }\r\n\r\n /**\r\n * Convert object to string representation for it's values.\r\n * @param {object} object - The object to convert\r\n * @returns {string}\r\n */\r\n export function objectToString(object: object): string {\r\n let value = \"\";\r\n let firstRun = true;\r\n\r\n if (typeof object !== \"object\") {\r\n return value;\r\n }\r\n\r\n // tslint:disable-next-line:forin\r\n for (let attribute in object) {\r\n if (typeof object[attribute] === \"object\") {\r\n value += firstRun ? `${objectToString(object[attribute])}` : `-${objectToString(object[attribute])}`;\r\n } else {\r\n value += firstRun ? `${object[attribute]}` : `-${object[attribute]}`;\r\n }\r\n\r\n firstRun = false;\r\n }\r\n\r\n return value;\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * An enumeration indicating the MSA sign in status for the page.\r\n */\r\nexport enum SignedInStatus {\r\n Unknown,\r\n NotSignedIn,\r\n SignedIn\r\n}\r\n\r\n/**\r\n * The various account types that we support in Peregrine, this enum can be modified as new types are added\r\n * 0 - MSA\r\n * 1 - AAD\r\n * 2 - SignedOut\r\n */\r\nexport enum AccountType {\r\n MSA = 0,\r\n AAD = 1,\r\n SignedOut = 2\r\n}\r\n\r\n/**\r\n * Note: these values are used by the Telemetry team and must remain in the following order:\r\n * 0 - NonAadAccount\r\n * 1 - AadAccount\r\n * 2 - Unknown\r\n */\r\nexport enum AadAccountType {\r\n NonAadAccount = 0,\r\n AadAccount = 1,\r\n Unknown = 2\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ActionMap } from \"@msnews/experiences-redux\";\r\nimport { ExperienceDeferralInfo } from \"./data-model/ExperienceDeferralInfo\";\r\nimport { ExperienceLoadingState } from \"./data-model/ExperienceLoadingState\";\r\nimport { MilestonePlugin } from \"./data-model\";\r\n\r\ntype UpdateExperienceCurrentStateSignature = (\r\n /** Experience Type - Defines an experience */\r\n experienceType: string,\r\n\r\n /** Current Milestone of the experience e.g initialized, loaded, deferred etc */\r\n currentState: ExperienceLoadingState,\r\n\r\n /** Associated Experience Group */\r\n experienceGroup?: string,\r\n\r\n /** Defines an instance of the Experience */\r\n experienceInstance?: string\r\n) => void;\r\n\r\ntype UpdateExperienceDeferralSignature = (\r\n /** Tracks deferral information used by an experience to determine when it should load/render */\r\n deferralInfo: ExperienceDeferralInfo,\r\n\r\n /** Experience Type - Defines an experience */\r\n experienceType: string,\r\n\r\n /** Associated Experience Group */\r\n experienceGroup?: string,\r\n\r\n /** Defines an instance of the Experience */\r\n experienceInstance?: string\r\n) => void;\r\n\r\ntype UpdateTimingSignature = (\r\n /** Experience Type - Defines an experience */\r\n experienceType: string,\r\n\r\n /** Associated Experience Group */\r\n experienceGroup?: string,\r\n\r\n /** Defines an instance of the Experience */\r\n experienceInstance?: string,\r\n\r\n /** start time fo the milestone e.g. startTime of loaded milestone */\r\n startTime?: number,\r\n\r\n /** end time fo the milestone e.g. endTime of loaded milestone */\r\n endTime?: number\r\n) => void;\r\n\r\ntype UpdatePluginSignature = (\r\n /** Plugins to add additional behaviors in page lifecycle events */\r\n plugins: MilestonePlugin[]\r\n) => void;\r\n\r\ntype UpdatePageTimingSignature = (endTime?: number) => void;\r\n\r\ntype UpdateBelowTheFoldTransitionSignature = (start?: boolean) => void;\r\n\r\n/**\r\n * Actions for the Milestone Data Connector\r\n * @class\r\n */\r\nexport class MilestoneDataActions {\r\n /** Action to trigger above the fold timing updates */\r\n public static updateAboveTheFoldVisuallyReady: ActionMap\r\n = new ActionMap(\"updateAboveTheFoldVisuallyReady\");\r\n\r\n /** Action to trigger below the fold transition updates */\r\n public static updateBelowTheFoldTransitionStart: ActionMap\r\n = new ActionMap(\"updateBelowTheFoldTransitionStart\");\r\n\r\n /** Action to trigger when deferring an experience load */\r\n public static updateExperienceLoadDeferralState: ActionMap\r\n = new ActionMap(\"updateExperienceLoadDeferralState\");\r\n\r\n /** Action to trigger when updating current state of experience in load/render life-cycle */\r\n public static updateExperienceCurrentState: ActionMap\r\n = new ActionMap(\"updateExperienceCurrentState\");\r\n\r\n /** Action to trigger when deferring an experience render */\r\n public static updateExperienceRenderDeferralState: ActionMap\r\n = new ActionMap(\"updateExperienceRenderDeferralState\");\r\n\r\n /** Action to trigger when experience load initiates */\r\n public static updateInitTiming: ActionMap\r\n = new ActionMap(\"UpdateInitTiming\");\r\n\r\n /** Action to trigger page complete timing updates */\r\n public static updatePageComplete: ActionMap\r\n = new ActionMap(\"updatePageCompleteTiming\");\r\n\r\n /** Action to trigger when experience instance completed render */\r\n public static updateRenderTiming: ActionMap\r\n = new ActionMap(\"UpdateRenderTiming\");\r\n\r\n /** Action to trigger when experience instance is visually ready */\r\n public static updateVisuallyReadyTiming: ActionMap\r\n = new ActionMap(\"UpdateVisuallyReadyTiming\");\r\n\r\n /** Action to trigger when experience instance is DOM complete */\r\n public static updateDomCompleteTiming: ActionMap\r\n = new ActionMap(\"UpdateDomCompleteTiming\");\r\n\r\n /** Action to trigger when adding/updating milestone plugin */\r\n public static updateMilestonePlugins: ActionMap\r\n = new ActionMap(\"updateMilestonePlugin\");\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n/**\r\n * Defines valid loading states for an experience\r\n * The state has been defined as it happens. Please do not update the ordering or the numeric value of states.\r\n * If the numeric value of the state is updated this will break internal logic.\r\n */\r\nexport enum ExperienceLoadingState {\r\n\r\n /**\r\n * The experience has not been started yet\r\n */\r\n notStarted = 1,\r\n\r\n /**\r\n * The experience loading has been deferred\r\n */\r\n loadDeferred = 2,\r\n\r\n /**\r\n * The experience is coming out of loadDeferred state and is now resolved to be loaded.\r\n */\r\n resolvedForLoad = 3,\r\n\r\n /**\r\n * The experience has been loaded (i.e. the bundle has been downloaded and parsed, and the connector created)\r\n */\r\n loaded = 4,\r\n\r\n /**\r\n * The experience initialized milestone has been reached\r\n */\r\n initialized = 5,\r\n\r\n /**\r\n * The experience render has been deferred\r\n */\r\n renderDeferred = 6,\r\n\r\n /**\r\n * The experience is coming out of renderDeferred state and is now resolved to be rendered.\r\n */\r\n resolvedForRender = 7,\r\n\r\n /**\r\n * The experience rendered milestone has been reached (render function has been completed)\r\n */\r\n rendered = 8,\r\n\r\n /**\r\n * The experience DOM complete milestone has been reached\r\n */\r\n domComplete = 10,\r\n\r\n /**\r\n * The initial render of the experience has completed. All initial DOM elements have been created, and the browser has completed all render\r\n * task (applying styles, animations, etc)\r\n */\r\n visuallyReady = 11,\r\n\r\n /**\r\n * The experience encountered an error during loading\r\n */\r\n error = 12\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Enum for different app types\r\n * @enum\r\n */\r\nexport enum AppType {\r\n Edge = \"edge\",\r\n EdgeChromium = \"edgeChromium\",\r\n Hub = \"hub\",\r\n MicrosoftNews = \"microsoftNews\",\r\n MMX = \"mmx\",\r\n Office = \"office\",\r\n Views = \"views\"\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { assign, get, merge, set } from \"lodash-es\";\r\n\r\nimport { ConnectorConstants } from \"../constants/ConnectorConstants\";\r\nimport { ConnectorNamespaces } from \"@msnews/experiences-constants\";\r\nimport { IActionPayload } from \"./IActionPayload\";\r\nimport { IDataConnector } from \"../connectors/IDataConnector\";\r\nimport { IReducer } from \"./IReducer\";\r\nimport { dataConnectorInjector } from \"./DataConnectorInjector\";\r\nimport { isNullOrUndefined } from \"util\";\r\n\r\n/** Resolve & Reject Function Signature */\r\ntype ResolveConnectorSignature = (connector: IDataConnector) => void;\r\ntype RejectConnectorSignature = (error: Error) => void;\r\n\r\n/**\r\n * Pending getDataConnector Promise\r\n */\r\ninterface PendingConnectorPromise {\r\n /** Promise */\r\n promise: Promise>;\r\n /** callback to resolve the promise */\r\n resolve: ResolveConnectorSignature;\r\n /** callback to reject the promise */\r\n reject: RejectConnectorSignature;\r\n}\r\n\r\n/** Result from running a reducer. */\r\ninterface ReducerResult {\r\n /** The new state calculated by the reducer */\r\n newState: any;\r\n\r\n /** True if the state changed. */\r\n stateChanged: boolean;\r\n}\r\n\r\n/**\r\n * A reducer that can dynamically add and remove individual sub-reducers\r\n * @class\r\n */\r\nexport class DynamicReducer {\r\n\r\n /**\r\n * A map of connectors, which maintain the sub-spaced state. Reducers and connectors are keyed by namespace\r\n */\r\n private readonly _connectorMap: {[key: string]: IDataConnector} = {};\r\n\r\n /**\r\n * The list of global connectors. Used for fast lookup instead of iterating through _connectorMap keys and toArray methods.\r\n */\r\n private readonly _globalConnectors: IDataConnector[] = [];\r\n\r\n /**\r\n * The list of all connectors. Used for fast lookup instead of iterating through _connectorMap keys and toArray methods.\r\n */\r\n private readonly _allConnectors: IDataConnector[] = [];\r\n\r\n /**\r\n * The list of all pending promises for the get data connector call. Used to resolve the promise when data connector is instantiated.\r\n */\r\n private readonly _getDataConnectorPendingPromises: Map = new Map();\r\n\r\n /**\r\n * Creates an instance of the `DynamicReducer` class.\r\n * @constructor\r\n * @param {string} type The action type.\r\n */\r\n constructor() {\r\n // bind the reduce method to this instance\r\n this.reduce = this.reduce.bind(this);\r\n }\r\n\r\n /**\r\n * Returns an array of connectors that have their reducers registered with this instance\r\n * @method\r\n * @returns {IDataConnector} A simple arry of all connectors\r\n */\r\n public connectors(): IDataConnector[] {\r\n return this._allConnectors;\r\n }\r\n\r\n /**\r\n * Returns an array of connectors that have their reducers registered with this instance\r\n * @method\r\n * @param {string} namespace The namespace of the connector to return, if it is in the map\r\n * @returns {IDataConnector | undefined} A simple arry of all connectors\r\n */\r\n public connector(namespace: string): IDataConnector | undefined {\r\n return (this._connectorMap[namespace]);\r\n }\r\n\r\n /**\r\n * Returns an array of connectors that have state that is global\r\n * @method\r\n * @returns {IDataConnector} A simple arry of connectors that have global state\r\n */\r\n public globalConnectors(): IDataConnector[] {\r\n return this._globalConnectors;\r\n }\r\n\r\n /**\r\n * Returns a promise which resolves immediately if the data connector is already present on the page,\r\n * otherwise resolves when the data connector is instantiated on the Page later in the lifecycle.\r\n * @method\r\n * @param namespace The namespace of data connector to return\r\n */\r\n public getDataConnector(namespace: ConnectorNamespaces): Promise> {\r\n // Check for data connector, if it is already present resolve immediately\r\n const dataConnector = this.connector(namespace);\r\n if (dataConnector) {\r\n return Promise.resolve(dataConnector);\r\n }\r\n\r\n // Check if we have an entry for the namespace in pending promise map, if present return the same promise\r\n const pendingPromise = this._getDataConnectorPendingPromises.get(namespace);\r\n if (pendingPromise) {\r\n return pendingPromise.promise;\r\n }\r\n\r\n // If the data connector is not on the page and has no entry in the pending promise map, create a new promise\r\n let resolveCallback: ResolveConnectorSignature;\r\n let rejectCallback: RejectConnectorSignature;\r\n const promise = new Promise>((resolve, reject) => {\r\n // Get the reference to the resolve & reject which can be called later when the data connector is instantiated on the Page\r\n resolveCallback = resolve;\r\n rejectCallback = reject;\r\n });\r\n\r\n // Add the promise to the pending promise map\r\n this._getDataConnectorPendingPromises.set(namespace, { promise: promise, resolve: resolveCallback, reject: rejectCallback });\r\n\r\n // Return the promise\r\n return promise;\r\n }\r\n\r\n /**\r\n * Produces the next state based on the given action. The state to be reduced is an aggregate of the reducers for all of the connectors\r\n * that have been added.\r\n * The overall state looks something like:\r\n * This will be the state for the redux-subspace for the connector. It is of the form:\r\n * {\r\n * FOO: {\r\n * _@STATE@_: {\r\n * \r\n * },\r\n * BAR: {\r\n * _@STATE@_: {\r\n * \r\n * },\r\n * },\r\n * }\r\n * }\r\n * @function\r\n * @param state {any} The previous state of the application. The application state, will contain one or more sub-states, which will be individually reduced\r\n * @param actionPayload {IActionPayload} The action detail to update the state with.\r\n * @returns {any} The next state for the application, containing the next state for each connector (a.k.a subspace)\r\n */\r\n public reduce(state: any, actionPayload: IActionPayload): any {\r\n // If the initial state is undefined, then create an empty object to start with\r\n if (isNullOrUndefined(state)) {\r\n state = {};\r\n }\r\n\r\n let newState = { ...state };\r\n let stateChanged = false;\r\n\r\n // See if we need to reduce for a specific connector. This is the common case.\r\n if (actionPayload !== undefined && actionPayload.key !== undefined) {\r\n // If this is a special action, used to force a re-render, then we need to set stateChanged to true, and create a clone of the existing scoped state\r\n const typeIsString: boolean = typeof actionPayload.type === \"string\";\r\n if (typeIsString && actionPayload.type.endsWith(ConnectorConstants.renderAction)) {\r\n const statePropertyKey = actionPayload.key + \".\" + ConnectorConstants.connectorStateKey;\r\n const connectorState = assign({}, get(state, statePropertyKey, undefined));\r\n set(newState, statePropertyKey, connectorState);\r\n stateChanged = true;\r\n } else if (typeIsString && actionPayload.type.endsWith(ConnectorConstants.dataConnectorMergeInitAction)) {\r\n const experienceFullNamespace: string = actionPayload.key;\r\n const dataConnectorName: ConnectorNamespaces = actionPayload.params[0];\r\n\r\n if (dataConnectorName) {\r\n dataConnectorInjector.initializeExperience(newState, experienceFullNamespace, dataConnectorName);\r\n stateChanged = true;\r\n }\r\n } else {\r\n // If the connector doing the reducing is global, then create a deep copy of state, so that all the connected\r\n // components think the state is new, and run their mappers. Connected components are subscribed to, and only see\r\n // changed in their subspace portion of the state tree. The redux connect implementation uses strict equal comparison,\r\n // meaning it consider the state change if it is a new object reference, even if all the properties are still the same\r\n if (this._connectorMap[actionPayload.key].isGlobal) {\r\n newState = merge({}, newState);\r\n }\r\n\r\n const connectorReducerResult = this.computeNextStateForConnector(newState, actionPayload.key, actionPayload);\r\n stateChanged = connectorReducerResult.stateChanged;\r\n\r\n if (stateChanged) {\r\n // Check to see if any experiences are including this data connector state. If so, update those too.\r\n dataConnectorInjector.reportStateChange(newState, actionPayload.key, connectorReducerResult.newState);\r\n }\r\n }\r\n } else {\r\n // Iterate over the full list of connectors calling each reducer. This is not the common case, and is typically done\r\n // for actions that come from Redux, during initialization\r\n Object.keys(this._connectorMap).forEach(key => {\r\n if (this.computeNextStateForConnector(newState, key, actionPayload).stateChanged) {\r\n stateChanged = true;\r\n }\r\n });\r\n }\r\n\r\n // Return the newState, as modified by the reducer(s) if it was changed, otherwise return the original state\r\n if (stateChanged) {\r\n return newState;\r\n } else {\r\n return state;\r\n }\r\n }\r\n\r\n /**\r\n * Adds a sub reducer for a connector to the sub-reducer collection.\r\n * @method\r\n * @param {IDataConnector} connector The connector to add.\r\n */\r\n public addSubReducerForConnector(connector: IDataConnector): void {\r\n if (!connector) {\r\n throw new Error(\"The parameter 'connector' cannot be null.\");\r\n }\r\n\r\n // Add the sub-reducer and connector into their maps, based on the connector's namespace\r\n const key = connector.fullNamespace;\r\n this._connectorMap[key] = connector;\r\n\r\n // update the all and global connector fast lookup lists\r\n this._allConnectors.push(connector);\r\n\r\n if (connector.isGlobal) {\r\n this._globalConnectors.push(connector);\r\n }\r\n\r\n // Check if there is a pending promise for the data connector\r\n // DO NOT CHANGE namespace to fullnamespace, data connectors are supposed to be queried using just the namespace by design.\r\n if (this._getDataConnectorPendingPromises.has(connector.namespace)) {\r\n // Get the resolve callback for the pending promise and resolve it\r\n const pendingPromise = this._getDataConnectorPendingPromises.get(connector.namespace);\r\n\r\n try {\r\n pendingPromise.resolve(connector);\r\n } catch (error) {\r\n pendingPromise.reject(error);\r\n }\r\n\r\n // Delete the entry from the pending promise map\r\n this._getDataConnectorPendingPromises.delete(connector.namespace);\r\n }\r\n\r\n connector.store.dispatch({ key: key, type: \"@@connector-view/INIT\" });\r\n }\r\n\r\n /**\r\n * Helper method to compute the next state for a given connector. This method will get the connector's actual state\r\n * from the state tree, call the reducer, and then state the state in the passed in object that is to receive the new state\r\n * @param {any} state The current subspace (or root) state object, which will be updated\r\n * @param {string} key The key to the connector in the connector map\r\n * @param {IActionPayload} actionPayload The action to apply\r\n * @returns Information on how the connector state was changed\r\n */\r\n private computeNextStateForConnector(state: any, key: string, actionPayload: IActionPayload): ReducerResult {\r\n // Get the connector, so that we can call the reducer\r\n const connector = this._connectorMap[key];\r\n\r\n // Setup the key and get the actual state property for the connector. lodash uses dotted notation\r\n // so the key will be something like: namespace._@STATE@_\r\n const statePropertyKey = key + \".\" + ConnectorConstants.connectorStateKey;\r\n const connectorPreviousState = get(state, statePropertyKey, undefined);\r\n\r\n // Call the reducer for the connector, and validate that we received a state object back.\r\n const nextStateForConnector = this.subReduce(connector.reducer, connectorPreviousState, actionPayload);\r\n if (typeof nextStateForConnector === \"undefined\") {\r\n throw new Error(\"Reducer for: \" + key + \" must not return undefined.\");\r\n }\r\n\r\n // If the state changed, then set the new connector state in the overall state object\r\n const connectorStateChanged: boolean = nextStateForConnector !== connectorPreviousState;\r\n if (connectorStateChanged) {\r\n set(state, statePropertyKey, nextStateForConnector);\r\n }\r\n\r\n return { newState: nextStateForConnector, stateChanged: connectorStateChanged };\r\n }\r\n\r\n /**\r\n * Calls the reducer that has been registered to handle the state associated with a specific subspace\r\n * @param {Reducer} reducer The reducer to call\r\n * @param {TSubReducerState} state The state object for the subreducer\r\n * @param {IActionPayload} actionPayload The action to apply\r\n */\r\n private subReduce(reducer: IReducer, previousState: TSubReducerState, actionPayload: IActionPayload): TSubReducerState {\r\n const reducedState: TSubReducerState = reducer.reduce(previousState, actionPayload);\r\n if (reducedState !== previousState) {\r\n return reducedState;\r\n } else {\r\n return previousState;\r\n }\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Weak map which is used to store DesignSystem to GenerateClassName Callback.\r\n */\r\nconst designSystemMap = new WeakMap();\r\n\r\n/**\r\n * Map which will store number of DesignSystem appearances with same name.\r\n */\r\nconst designSystemIndexMap = new Map();\r\n\r\n/**\r\n * JSS callback function that defines the class name generation logic\r\n * The default jss manager class name generation logic increments counter based on order\r\n * of how the experiences are rendered. We cannot guarantee the order due to async nature\r\n * of experiences which potentially causes different class names on every reload/refresh.\r\n * Instead here with this callback, we start the counter from 1 per rule to ensure class\r\n * names stays consistent irrespective of when they are rendered.\r\n *\r\n * Design system is taken into account since a change in it can result in potential different\r\n * styling being needed even if that rule was already used in a previous design system.\r\n *\r\n * For example:\r\n * For TopSites, with this override the class name would be generated as \"topSites-DS-default1-1\"\r\n * (jss manager by default would have generated it something like \"topSites-0-1-305\")\r\n * If the design system were to be updated and the same rule would be passed then you would\r\n * get topsites-DS-default2-1.\r\n */\r\nexport function createGenerateClassName(designSystem: any): (rule: any, sheet: any) => string {\r\n if (!designSystem) {\r\n return;\r\n }\r\n\r\n let callback = designSystemMap.get(designSystem);\r\n\r\n if (!callback) {\r\n const dsName = designSystem.name || \"unknown\";\r\n const dsIndex = designSystemIndexMap.get(dsName) + 1 || 1;\r\n let rulesMap: any = {};\r\n callback = (rule: any, sheet: any) => {\r\n const key = rule.key;\r\n\r\n if (!rulesMap[key]) {\r\n rulesMap[key] = 1;\r\n } else {\r\n rulesMap[key]++;\r\n }\r\n return `${key}-DS-${dsName}${dsIndex}-${rulesMap[key]}`;\r\n };\r\n\r\n designSystemMap.set(designSystem, callback);\r\n designSystemIndexMap.set(dsName, dsIndex);\r\n }\r\n\r\n return callback;\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { Provider, connect } from \"react-redux\";\r\nimport { Store, StoreEnhancer, compose, createStore } from \"redux\";\r\nimport { getPageTimings, logger } from \"@msnews/diagnostics\";\r\n\r\nimport { DynamicReducer } from \"../reducers\";\r\nimport { IDataConnector } from \"../connectors/IDataConnector\";\r\nimport { JSSManager } from \"@microsoft/fast-jss-manager-react\";\r\nimport React from \"react\";\r\nimport ReactDom from \"react-dom\";\r\nimport { applyMiddleware } from \"redux-subspace\";\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\nimport { create } from \"jss\";\r\nimport { createGenerateClassName } from \"./PageHelper\";\r\nimport { getStateFromRenderCache } from \"@msnews/render-cache\";\r\nimport jssGlobal from \"jss-global\";\r\nimport jssNested from \"jss-nested\";\r\n\r\ndeclare global {\r\n interface Window {\r\n /**\r\n * Enable redux devtools extension debugging\r\n */\r\n __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: any;\r\n\r\n /**\r\n * Boolean flag to indicate if render cache hydration is happening\r\n */\r\n needsHydrate?: boolean;\r\n }\r\n}\r\n\r\n/**\r\n * Page Base.\r\n * Each page or hybrid page/experience must have an instance of the PageBase, which contains the the store, and dynamic reducer\r\n * for the experience/app.\r\n * PageBase is setup as a singleton, so the proper usage in consumers is:\r\n * var pageBase = PageBase.getInstance();\r\n * @export\r\n * @class\r\n */\r\nclass PageBase {\r\n /**\r\n * The singleton instance of this class\r\n * @type: {PageBase}\r\n */\r\n private static _instance: PageBase;\r\n\r\n /**\r\n * The Dynamic reducer for this app/experience\r\n * @type: {DynamicReducer}\r\n */\r\n private _rootReducer: DynamicReducer;\r\n\r\n /**\r\n * The Redux store containing the top level application state. All component and data connectors will manage namespaced subspaces within\r\n * this store\r\n * @type {Store}\r\n */\r\n private _store: Store;\r\n\r\n /**\r\n * @constructor\r\n */\r\n private constructor() {\r\n /**\r\n * In debug build, add the option to turn on redux-devtools-extension debugging.\r\n * More info here https://github.com/zalmoxisus/redux-devtools-extension\r\n */\r\n let enhancer: StoreEnhancer;\r\n const middlewares: any = [];\r\n if (canUseDOM() && logger.isDebug()) {\r\n const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ trace: true, traceLimit: 25 }) || compose;\r\n enhancer = composeEnhancers(applyMiddleware(...middlewares)\r\n );\r\n } else {\r\n enhancer = applyMiddleware(...middlewares);\r\n }\r\n\r\n // Create the root reducer\r\n this._rootReducer = new DynamicReducer();\r\n\r\n // Check to see if this app instance was bootstrapped with a render-cache\r\n const initialState = canUseDOM() && window.needsHydrate && getStateFromRenderCache() || {};\r\n\r\n // create the store with a basic root reducer\r\n this._store = createStore(this.rootReducer.reduce, initialState, enhancer);\r\n }\r\n\r\n /**\r\n * Gets the Redux store for this app/experience\r\n * @method\r\n * @returns {Store} The overall state for the App, which contains sub-states for each connector\r\n */\r\n public get store(): Store {\r\n return this._store;\r\n }\r\n\r\n /**\r\n * Gets the root reducer for this app/experience\r\n * @returns {DynamicReducer} The reducer for the app/experience\r\n */\r\n public get rootReducer(): DynamicReducer {\r\n return this._rootReducer;\r\n }\r\n\r\n /**\r\n * Gets the singleton instance of this class for the app/experience\r\n * @returns {PageBase} The instance of PageBase for the page/hybrid experience\r\n */\r\n public static getInstance(): PageBase {\r\n return this._instance || (this._instance = new this());\r\n }\r\n\r\n /**\r\n * Starts the application by calling the onApplicationStart method for each connector that has been added to the app.\r\n * @function\r\n * @method\r\n */\r\n public start(): void {\r\n // Iterate over all of the connector's and call their OnApplicationStart method\r\n const allConnectors: IDataConnector[] = this.rootReducer.connectors();\r\n allConnectors.forEach(connector => connector.onApplicationStart());\r\n }\r\n\r\n /**\r\n * Creates and renders a root element, that is connected to the store.\r\n * The root element will created with the passed in connected element as a child.\r\n * @function\r\n * @param {React.ReactElement} connectedTopLevelElement The top level rendering element for the page/application.\r\n * @param {HTMLElement} hostElement The host element (usuall a
) to contain the msnews-experiences-redux application\r\n * @method\r\n */\r\n public renderRootElement(connectedTopLevelElement: React.ReactElement, hostElement: HTMLElement): void {\r\n // Update the base JSS manager instance\r\n this.updateJssManagerInstance();\r\n\r\n // Create a ReactElement, that contains the Redux provider with the store, passing the incomming top level element in as a child, so that\r\n // the pageElement wraps the top level element with the redux store\r\n const rootElement = React.createElement(Provider, { store: this._store }, connectedTopLevelElement);\r\n\r\n // Capture Render cache state in page timings\r\n let pageTimings = getPageTimings();\r\n\r\n if (window.needsHydrate) {\r\n ReactDom.hydrate(rootElement, hostElement);\r\n pageTimings[\"isRenderCachePresent\"] = 1;\r\n window.needsHydrate = false;\r\n } else {\r\n pageTimings[\"isRenderCachePresent\"] = 0;\r\n ReactDom.render(rootElement, hostElement);\r\n }\r\n }\r\n\r\n /**\r\n * Updates the base JSSManager instance with the correct default plugins\r\n */\r\n private updateJssManagerInstance(): void {\r\n const jssInstance: ReturnType = create({\r\n plugins: [jssNested(), jssGlobal()]\r\n });\r\n\r\n JSSManager.createGenerateClassName = createGenerateClassName;\r\n JSSManager.jss = jssInstance;\r\n }\r\n}\r\n\r\nexport default PageBase;","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\n\r\nlet savedMuid: string = null;\r\n\r\n/**\r\n * Returns the cookie content given a name\r\n *\r\n * @param name {string} - cookie name\r\n * @returns the value of the cookie or `null`, if the key is not found.\r\n */\r\nexport function getCookie(name: string): string {\r\n if (canUseDOM() && document && document.cookie) {\r\n var re = new RegExp(\"\\\\b\" + name + \"\\\\s*=\\\\s*([^;]*)\", \"i\");\r\n var match = re.exec(document.cookie);\r\n return (match && match.length > 1 ? match[1] : null);\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Helper function that retrieves the MUID from the document.cookie\r\n * or uses the saved value if the cookie was retrieved for the current page instance\r\n */\r\nexport function getMuidCookie(): string {\r\n return savedMuid || (savedMuid = getCookie(\"MUID\"));\r\n}\r\n\r\n/**\r\n * Helper function used to set a cookie\r\n * NOTE: THIS BYPASSES ANY GDPR CHECK AND HENCE ONLY REQUIRED FUNCTIONAL COOKIES SHOULD BE SET USING THIS\r\n * IF YOU DO NOT KNOW IF YOUR COOKIE IS ONE THEN PLEASE USE Cookies.ts setCookie THAT MAKES USE OF GDPR LOGIC CHECKS\r\n * When expiryDays is equal to -1 it will unset the cookie\r\n * * @param {string} name Cookie name\r\n * * @param {string} value Cookie value\r\n * * @param {number} expiryDays Cookie expiry days\r\n * * @param {string} domain Cookie domain\r\n * * @param {string} path Cookie path\r\n * * @param {boolean} secure Is it a https only cookie\r\n */\r\nexport function setRequireFunctionalCookie(name: string, value: string, expiryDays?: number, domain?: string, path?: string, secure?: boolean): void {\r\n let expiryDate;\r\n const builder = [name, \"=\", value];\r\n if (-1 === expiryDays) {\r\n // Expires date format is supposed to be in GMT.\r\n expiryDate = \"Fri, 31 Dec 1999 23:59:59 GMT\";\r\n } else if (expiryDays) {\r\n const date = new Date();\r\n date.setTime(date.getTime() + (expiryDays * 86400000)); // 86400000 == 24*60*60*1000 (ms/day)\r\n expiryDate = date.toUTCString();\r\n }\r\n\r\n if (expiryDate) { builder.push(\";expires=\", expiryDate); }\r\n if (domain) { builder.push(\";domain=\", domain); }\r\n if (path) { builder.push(\";path=\", path); }\r\n if (secure) { builder.push(\";secure\"); }\r\n\r\n if (canUseDOM() && document) {\r\n document.cookie = builder.join(\"\");\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport PageBase from \"./PageBase\";\r\n\r\nexport default PageBase;\r\nexport * from \"./PageBase\";\r\n","// © Microsoft Corporation. All rights reserved.\r\n// Provides utility functions to get and set data from browser webStorage.\r\n\r\nimport { tryParseJson } from \"../utilities/Parsing\";\r\nimport { logger } from \"@msnews/diagnostics\";\r\n\r\n/**\r\n * Base class for localeStorage and sessionStorage abstractions\r\n */\r\nexport class WebStorage {\r\n /**\r\n * Local storage object for persistent storage\r\n */\r\n constructor(private readonly storage: Storage) {\r\n }\r\n\r\n /**\r\n * Check if the web storage is supported\r\n * @returns {boolean} true if supported\r\n */\r\n public get supported(): boolean {\r\n return !!this.storage;\r\n }\r\n\r\n /**\r\n * Get given key's value from web storage\r\n * @param {string} key - Key name\r\n * @returns {string} Key value\r\n */\r\n public getItem(key: string): string {\r\n if (this.supported) {\r\n return this.storage.getItem(key);\r\n }\r\n }\r\n\r\n /**\r\n * Gets the value from local storage using the key.\r\n * @param {string} key - the storage key to store under\r\n * @param {T} defaultValue - the default value to return if parsing fails\r\n * @returns {T} The parsed JSON value\r\n */\r\n public getObject(key: string, defaultValue?: T): T {\r\n let value = this.getItem(key);\r\n if (value != null) {\r\n let parsedObj = tryParseJson(value);\r\n if (parsedObj != null) {\r\n return parsedObj;\r\n }\r\n }\r\n\r\n return defaultValue;\r\n }\r\n\r\n /**\r\n * Gets given index location key from web storage\r\n * @param {string} key - Key name\r\n * @returns {string} Key value\r\n */\r\n public key(index: number): string {\r\n if (this.supported && index >= 0) {\r\n return this.storage.key(index);\r\n }\r\n }\r\n\r\n /**\r\n * Sets the given value after stringifying as JSON\r\n * @param {string} key - the storage key to store under\r\n * @param {T} value - the value to serialize and store\r\n */\r\n public setObject(key: string, value: T): void {\r\n (value !== undefined)\r\n ? this.setItem(key, JSON.stringify(value))\r\n : this.removeItem(key);\r\n }\r\n\r\n /**\r\n * Removes the given key from storage and returns the existing value parsed\r\n * @param {string} key - the key to remove.\r\n */\r\n public removeObject(key: string): T {\r\n let value = this.removeItem(key);\r\n if (value != null) {\r\n return tryParseJson(value);\r\n }\r\n }\r\n\r\n /**\r\n * Set given key's value to local storage\r\n * @param {string} key - Key name\r\n * @param {string} value - Key value\r\n */\r\n public setItem(key: string, value: string): void {\r\n if (this.supported) {\r\n // Catch quota exceeded exception\r\n try {\r\n this.storage.setItem(key, value);\r\n } catch (e) {\r\n logger.logError(e);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Remove key item from local storage\r\n * @param {string} key - Key name\r\n * @returns {string} Key value\r\n */\r\n public removeItem(key: string): string {\r\n if (this.supported) {\r\n let value = this.getItem(key);\r\n this.storage.removeItem(key);\r\n return value;\r\n }\r\n }\r\n\r\n /**\r\n * Removes all keys containing the given substring in the storage key\r\n * @param {string} substring The substring to check\r\n */\r\n public removeSubstringKeys(substring: string): void {\r\n if (!this.supported || !substring) {\r\n return;\r\n }\r\n\r\n let matchingKeys = [];\r\n for (let index = 0; index < this.storage.length; index++) {\r\n const storageKey = this.key(index);\r\n if (storageKey && storageKey.includes(substring)) {\r\n matchingKeys.push(storageKey);\r\n }\r\n }\r\n\r\n for (let index = 0; index < matchingKeys.length; index++) {\r\n this.removeItem(matchingKeys[index]);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Local storage class for persistent storage\r\n */\r\nexport class LocalStorage extends WebStorage {\r\n constructor() {\r\n let storage: Storage;\r\n\r\n try {\r\n storage = \"localStorage\" in window && window.localStorage;\r\n } catch (ex) {\r\n // Getting local storage failed. Can happen in Chrome when user has disabled cookies.\r\n }\r\n\r\n super(storage);\r\n }\r\n}\r\n\r\n/**\r\n * Session storage class for persistent storage\r\n */\r\nexport class SessionStorage extends WebStorage {\r\n constructor() {\r\n let storage: Storage;\r\n\r\n try {\r\n storage = \"sessionStorage\" in window && window.localStorage;\r\n } catch (ex) {\r\n // Getting session storage failed. Can happen in Chrome when user has disabled cookies.\r\n }\r\n\r\n super(storage);\r\n }\r\n}\r\n\r\nexport const localStorage = new LocalStorage();\r\nexport const sessionStorage = new SessionStorage();","// © Microsoft Corporation. All rights reserved.\r\n\r\n\r\nexport enum Environment {\r\n prod = \"prod\",\r\n int1 = \"int1\",\r\n int = \"int\",\r\n intpr = \"intPR\",\r\n intpef = \"intPef\"\r\n}\r\n\r\n/**\r\n * Parses from string to Environment enum.\r\n * Defaults to null\r\n *\r\n * @export\r\n * @param {(string | null | undefined)} environment - string being parsed\r\n * @returns {(Environment | null)} - the parsed Environment enum, or null.\r\n */\r\nexport function getEnvironmentFromString(environment: string | null | undefined): Environment | null {\r\n switch (environment) {\r\n case Environment.prod:\r\n return Environment.prod;\r\n case Environment.int1:\r\n return Environment.int1;\r\n case Environment.int:\r\n case Environment.intpr:\r\n case Environment.intpef:\r\n return Environment.int;\r\n default:\r\n return null;\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nexport const Size1ColumnWidth: number = 300;\r\nexport let Size2ColumnWidth: number = 624;\r\nexport let Size3ColumnWidth: number = 948;\r\nexport let Size4ColumnWidth: number = 1272;\r\nexport let GutterSize: number = 24;\r\n\r\n/** Updates the current ColumnWidths based on changes in gutterSize */\r\nexport function updateColumnWidths(gutterSize: number): void {\r\n GutterSize = gutterSize;\r\n Size4ColumnWidth = (Size1ColumnWidth * 4) + (gutterSize * 3);\r\n Size3ColumnWidth = (Size1ColumnWidth * 3) + (gutterSize * 2);\r\n Size2ColumnWidth = (Size1ColumnWidth * 2) + gutterSize;\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { getLocationHref } from \"@msnews/isomorphic-util\";\r\n\r\n/**\r\n * localStorage key prefix for render cache object\r\n */\r\nexport const storagePrefix = `lastKnown_`;\r\n\r\n/**\r\n * localStorage key prefix for render cache expiration timestamp\r\n */\r\nexport const expirationPrefix = `timestamp_`;\r\n\r\n/**\r\n * localStorage key for render cache object\r\n */\r\nexport const renderCacheKey = `${storagePrefix}${getLocationHref()}`;\r\n\r\n/**\r\n * localStorage key for render cache expiration timestamp\r\n */\r\nexport const renderCacheExpirationKey = `${expirationPrefix}${getLocationHref()}`;\r\n\r\n/**\r\n * render-cache expiration time in ms\r\n * 86400000 = 24 hours in milliseconds\r\n */\r\nexport const defaultExpirationTimeMs = 86400000;\r\n\r\n/**\r\n * River Render Cache ClassName\r\n */\r\nexport const riverRcClassName = \"river-rc\";","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ConnectorNamespaces } from \"@msnews/experiences-constants\";\r\nimport { ExperiencesSharedStateConnector } from \"@msnews/experiences-shared-state\";\r\nimport { PageBase } from \"@msnews/experiences-redux\";\r\nimport { getAppEnvironment } from \"@msnews/core\";\r\n\r\n/**\r\n * chrome\r\n * The chrome API is not defined in Typescript\r\n */\r\ndeclare global {\r\n // tslint:disable-next-line: completed-docs\r\n interface Window { chrome: any; }\r\n}\r\n\r\n/** The aadToken QS key */\r\nexport const aadTokenQsKey = \"stn\";\r\n\r\n/** The aadToken QS value */\r\nexport const aadTokenQsVal = \"aad\";\r\n\r\n/**\r\n * Gets a value to indicate if we are in an enterprise scenario\r\n * eg. whether we should append the AAD Token as part of the call to oneservice endpoints\r\n * The default value is false, so we don't need to wait until the value is explicitly set\r\n */\r\nexport function useEnterpriseCompliance(): boolean {\r\n // Obtain the current value of useEnterpriseCompliance from the ExperiencesSharedState connector\r\n const sharedStateConnector: ExperiencesSharedStateConnector = PageBase.getInstance().rootReducer.connector(ConnectorNamespaces.SharedState) as ExperiencesSharedStateConnector;\r\n return sharedStateConnector ? sharedStateConnector.getCurrentState().useEnterpriseCompliance : false;\r\n}\r\n\r\n/**\r\n * Checks if we were able to get a valid aad token for this user\r\n */\r\nexport function isValidAadToken(): boolean {\r\n const appEnvironment = getAppEnvironment();\r\n\r\n return appEnvironment.AadData && appEnvironment.AadData.isSuccess && appEnvironment.AadData.isValid;\r\n}\r\n/**\r\n * Gets a value to indicate if we should use enterprise domain\r\n * eg. whether we should use the Falcon domain vs. consumer domain for oneservice requests\r\n * The default value is false, so we don't need to wait until the value is explicitly set\r\n */\r\nexport function useEnterpriseDomain(): boolean {\r\n // Obtain the current value of useEnterpriseDomain from the ExperiencesSharedState connector\r\n const sharedStateConnector: ExperiencesSharedStateConnector = PageBase.getInstance().rootReducer.connector(ConnectorNamespaces.SharedState) as ExperiencesSharedStateConnector;\r\n return sharedStateConnector ? sharedStateConnector.getCurrentState().useEnterpriseDomain : false;\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\n\r\nconst pageTimings = canUseDOM() ? (window._pageTimings || (window._pageTimings = {})) : null;\r\n\r\n/**\r\n * Gets current window._pageTimings object\r\n */\r\nexport function getPageTimings(): object {\r\n return pageTimings;\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { Size1ColumnWidth, Size2ColumnWidth, Size3ColumnWidth, Size4ColumnWidth } from \"./ColumnWidths\";\r\n\r\nimport { findIndex } from \"lodash-es\";\r\nimport { toPx } from \"@microsoft/fast-jss-utilities\";\r\n\r\n/**\r\n * Describes possible arragements of columns. For example c3 represents 3 columns.\r\n * \r\n * Each arrangement is valid for a particular range of window widths. For example, for window widths from 996px to 1319px,\r\n * we will use the c3 arrangement, or 3 columns.\r\n * \r\n * Currently each arrangement describes a column count, but in the future, there may be separate 3-column \"large\"\r\n * and 3-column \"small\" arrangements, like on msn.com.\r\n */\r\nexport enum ColumnArrangement {\r\n c1 = \"c1\",\r\n c2 = \"c2\",\r\n c3 = \"c3\",\r\n c4 = \"c4\"\r\n}\r\n\r\nlet minViewportWidthOverrides: Map;\r\n\r\n/**\r\n * Override the min viewport widths for the given column arrangements.\r\n * @param overrides The overrides to use for the column arrangements.\r\n */\r\nexport function overrideMinViewportWidths(overrides: Map): void {\r\n minViewportWidthOverrides = overrides;\r\n}\r\n\r\n/**\r\n * Defines the properties of a particular column arrangement.\r\n */\r\nexport class ColumnArrangementDefinition {\r\n /**\r\n * Creates a column arrangement definition.\r\n * @param arrangement The column arrangement being defined.\r\n * @param contentSizePx The size of the content in pixels for this arrangement.\r\n * @param isFirstBreakpoint True if this is the first breakpoint.\r\n */\r\n constructor(public arrangement: ColumnArrangement, public contentSizePx: number, private isFirstBreakpoint?: boolean) {}\r\n\r\n /**\r\n * Gets the minimum required window width to trigger this column arrangement.\r\n */\r\n public get minViewportWidthPx(): number {\r\n if (this.isFirstBreakpoint) {\r\n return 0;\r\n }\r\n\r\n if (minViewportWidthOverrides) {\r\n const widthOverride = minViewportWidthOverrides.get(this.arrangement);\r\n if (widthOverride) {\r\n return widthOverride;\r\n }\r\n }\r\n\r\n return this.contentSizePx + contentBufferPx;\r\n }\r\n}\r\n\r\n/**\r\n * The list of possible column arrangement definitions. Use this to determine what window sizes are\r\n * appropriate for each column arrangement.\r\n */\r\nexport const columnArrangements: ColumnArrangementDefinition[] = [\r\n new ColumnArrangementDefinition(ColumnArrangement.c1, Size1ColumnWidth, true),\r\n new ColumnArrangementDefinition(ColumnArrangement.c2, Size2ColumnWidth),\r\n new ColumnArrangementDefinition(ColumnArrangement.c3, Size3ColumnWidth),\r\n new ColumnArrangementDefinition(ColumnArrangement.c4, Size4ColumnWidth)\r\n];\r\n\r\n/**\r\n * A map of column arrangements to definitions.\r\n */\r\nconst columnArrangementMap: { [columnArrangement in ColumnArrangement]?: ColumnArrangementDefinition } = {};\r\nfor (let columnArrangementDefinition of columnArrangements) {\r\n columnArrangementMap[columnArrangementDefinition.arrangement] = columnArrangementDefinition;\r\n}\r\n\r\n/**\r\n * The number of pixels to add on top of the content width in order to get the window width required to show it.\r\n * This buffer guarantees space between the content and the edge of the window, and also space for the scrollbar,\r\n * which is also counted when determining breakpoints.\r\n */\r\nconst contentBufferPx: number = 32;\r\n\r\n/**\r\n * Gets the content width for the given column arrangement.\r\n * @param columnArrangement The column arrangement to look up.\r\n * @returns The width in pixels of the content.\r\n */\r\nexport function contentWidthPxForColumnArrangement(columnArrangement: ColumnArrangement): number {\r\n return columnArrangementMap[columnArrangement].contentSizePx;\r\n}\r\n\r\n/**\r\n * Gets the minimum window width for the given column arrangement.\r\n * @param columnArrangement The column arrangement to look up.\r\n * @returns The minimum width for the window to show this column arrangement.\r\n */\r\nexport function minWindowWidthPxForColumnArrangement(columnArrangement: ColumnArrangement): number {\r\n return columnArrangementMap[columnArrangement].minViewportWidthPx;\r\n}\r\n\r\n/**\r\n * Gets the maximum window width for the given column arrangement.\r\n * @param columnArrangement The column arrangement to look up.\r\n * @returns The maximum width for the window to show this column arrangement. NaN if there is no maximum.\r\n */\r\nexport function maxWindowWidthPxForColumnArrangement(columnArrangement: ColumnArrangement): number {\r\n const arrangementIndex = findIndex(columnArrangements, a => a.arrangement === columnArrangement);\r\n\r\n if (arrangementIndex < columnArrangements.length - 1) {\r\n return columnArrangements[arrangementIndex + 1].minViewportWidthPx - 1;\r\n }\r\n\r\n return NaN;\r\n}\r\n\r\n/**\r\n * Helper to efficiently get the media query string to be used for given min/max column arrangements\r\n * It can be used in conjuction with `window.matchMedia` to target specific page widths, and it is also\r\n * used internally to generate the equivalent css selectors in `getMediaQuerySelector`\r\n * @param minArragement The min column arrangement to use for the @media query (inclusive)\r\n * @param maxArrangement The max column arrangement to use for the @media query (inclusive)\r\n * @returns the @media query for the specified min/max.\r\n */\r\nexport function getMediaQuery(minArragement: ColumnArrangement | null, maxArrangement: ColumnArrangement | null): string {\r\n const queries = [];\r\n\r\n if (minArragement) {\r\n const minArrangementDefinition = columnArrangementMap[minArragement];\r\n const minWidthPx = minArrangementDefinition.minViewportWidthPx;\r\n\r\n if (minWidthPx > 0) {\r\n queries.push(`(min-width: ${toPx(minWidthPx)})`);\r\n }\r\n }\r\n\r\n if (maxArrangement) {\r\n const maxArrangementDefinition = columnArrangementMap[maxArrangement];\r\n const maxArrangementIndex = columnArrangements.indexOf(maxArrangementDefinition);\r\n\r\n if (maxArrangementIndex < columnArrangements.length - 1) {\r\n queries.push(`(max-width: ${toPx(columnArrangements[maxArrangementIndex + 1].minViewportWidthPx - 1)})`);\r\n }\r\n }\r\n\r\n return queries.join(\" and \");\r\n}\r\n\r\n/**\r\n * Helper to efficiently get the media query string to be used for the given column arrangement\r\n * It can be used in conjuction with `window.matchMedia` to target specific page widths, and it is also\r\n * used internally to generate the equivalent css selectors in `getMediaQuerySelector`\r\n * @param columnArrangement The column arrangement to target\r\n * @returns The media query to target that column arrangement\r\n */\r\nexport function getMediaQueryFor(columnArrangement: ColumnArrangement): string {\r\n return getMediaQuery(columnArrangement, columnArrangement);\r\n}\r\n\r\n/**\r\n * Helper to efficiently get the CSS selector to be used for apply styles for given min/max arrangements\r\n * @param minArragement The min column arrangement to use for the media query (inclusive)\r\n * @param maxArrangement The max column arrangement to use for the media query (inclusive)\r\n * @returns the css media query selector for the specified min/max.\r\n */\r\nexport function getMediaQuerySelector(minArragement: ColumnArrangement | null, maxArrangement: ColumnArrangement | null): string {\r\n const mediaQuery = getMediaQuery(minArragement, maxArrangement);\r\n return mediaQuery ? \"@media \" + mediaQuery : \"\";\r\n}\r\n\r\n/**\r\n * Helper to efficiently get the CSS selector to be used for apply styles for the given column arrangement.\r\n * @param columnArrangement The column arrangement to target\r\n * @returns the css media query selector for the specified column arrangement.\r\n */\r\nexport function getMediaQuerySelectorFor(columnArrangement: ColumnArrangement): string {\r\n return getMediaQuerySelector(columnArrangement, columnArrangement);\r\n}\r\n\r\n/**\r\n * Callback type for subscribing to BreakpointManager breakpoint changed events.\r\n */\r\nexport type BreakpointManagerCallback = (columnArrangement: ColumnArrangement) => void;\r\n\r\n/**\r\n * Breakpoint manager common interface.\r\n */\r\nexport interface BreakpointManager {\r\n /**\r\n * Gets the current column arrangement.\r\n */\r\n currentColumnArrangement: ColumnArrangement;\r\n\r\n /**\r\n * Subscribes for changes\r\n * @param callback The method to call when the column arrangement changes.\r\n */\r\n subscribe(callback: BreakpointManagerCallback): void;\r\n\r\n /**\r\n * Unsubscribe from changes\r\n * @param callback The callback to unregister.\r\n */\r\n unsubscribe(callback: BreakpointManagerCallback): void;\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Helper to promisify the Prime 'require' AMD helper to resolve a single module with no dependencies.\r\n * @param moduleName {string} - the name of the module to resolve\r\n * @param defaultModule {TModule} - the default module implementation if require is not available.\r\n * @returns {Promise{TModule}} a promise that will resolve the module when it's available.\r\n * @description Note that this version only resolves a single module with no dependencies.\r\n */\r\nexport async function requireAsync(moduleName: string, defaultModule?: TModule): Promise {\r\n return new Promise((resolve: (module: TModule) => void, reject) => {\r\n\r\n if (typeof window.require === \"function\") {\r\n window.require([moduleName], resolve);\r\n } else if (defaultModule) {\r\n console.error(`require was not available. Returning default implementation for ${moduleName}`);\r\n resolve(defaultModule);\r\n } else {\r\n reject(\"require is not available\");\r\n }\r\n });\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { get, set } from \"lodash-es\";\r\n\r\nimport { ConnectorConstants } from \"../constants/ConnectorConstants\";\r\nimport { ConnectorNamespaces } from \"@msnews/experiences-constants\";\r\n\r\n/**\r\n * Maps the data connector name to the set of experience keys it is injected into.\r\n * The values include the \"._@STATE@_\" portion needed to pull experience state out of the app state object.\r\n */\r\nconst dataConnectorToExperienceKeyMap: Map> = new Map>();\r\n\r\n/**\r\n * Register a data connector to inject into an experience.\r\n * @param experienceFullNamespace The full namespace of the experience to inject into.\r\n * @param dataConnectorName The name for the data connector to inject.\r\n */\r\nfunction registerInjection(\r\n experienceFullNamespace: string,\r\n dataConnectorName: ConnectorNamespaces): void {\r\n let experienceSet: Set = dataConnectorToExperienceKeyMap.get(dataConnectorName);\r\n if (!experienceSet) {\r\n experienceSet = new Set();\r\n dataConnectorToExperienceKeyMap.set(dataConnectorName, experienceSet);\r\n }\r\n\r\n experienceSet.add(createStatePropertyKey(experienceFullNamespace));\r\n}\r\n\r\n/**\r\n * Initializes the shared data connector state for the given experience.\r\n * @param appState The global app state to modify.\r\n * @param experienceFullNamespace The full namespace of the experience to host the data connector state.\r\n * @param dataConnectorName The name of the data connector to use.\r\n */\r\nfunction initializeExperience(\r\n appState: any,\r\n experienceFullNamespace: string,\r\n dataConnectorName: ConnectorNamespaces): void {\r\n\r\n // Setup the key and get the actual state property for the connector. lodash uses dotted notation\r\n // so the key will be something like: namespace._@STATE@_\r\n const experienceStatePropertyKey = createStatePropertyKey(experienceFullNamespace);\r\n const connectorPreviousState = get(appState, experienceStatePropertyKey, undefined);\r\n\r\n // Find the initial data connector state\r\n const initialDataConnectorState = get(appState, createStatePropertyKey(dataConnectorName), undefined);\r\n\r\n // Create the new experience connector state\r\n const nextStateForConnector = { ...connectorPreviousState, [dataConnectorName]: initialDataConnectorState };\r\n set(appState, experienceStatePropertyKey, nextStateForConnector);\r\n}\r\n\r\n/**\r\n * Updates the data connector state on all experiences that include it.\r\n * @param appState The global app state object.\r\n * @param dataConnectorNamespace The namespace of the data connector that's been updated.\r\n * @param newDataConnectorState The new data connector state object.\r\n */\r\nfunction reportStateChange(\r\n appState: any,\r\n dataConnectorNamespace: string,\r\n newDataConnectorState: any): void {\r\n\r\n const experienceKeys: Set = dataConnectorToExperienceKeyMap.get(dataConnectorNamespace);\r\n if (experienceKeys) {\r\n for (let experienceKey of experienceKeys) {\r\n const experiencePreviousState: any = get(appState, experienceKey, undefined);\r\n\r\n if (experiencePreviousState) {\r\n set(appState, experienceKey, { ...experiencePreviousState, [dataConnectorNamespace]: newDataConnectorState });\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Creates the lodash property key to get or set the experience or data connector state.\r\n * @param fullNamespace The full namespace of the experience or data connector.\r\n */\r\nfunction createStatePropertyKey(fullNamespace: string): string {\r\n return fullNamespace + \".\" + ConnectorConstants.connectorStateKey;\r\n}\r\n\r\n/** Methods to support injecting data connector state into experiences */\r\nexport const dataConnectorInjector = {\r\n registerInjection,\r\n initializeExperience,\r\n reportStateChange\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Aad data formatted from browser response\r\n */\r\nexport type AadData = {\r\n /**\r\n * Access token\r\n */\r\n token: string;\r\n\r\n /**\r\n * Any error info\r\n */\r\n errorInfo: AadErrorInfo;\r\n\r\n /**\r\n * Flag to indicate if call was successful\r\n */\r\n isSuccess: boolean;\r\n\r\n /**\r\n * Flag to indicate if token is valid\r\n */\r\n isValid: boolean;\r\n};\r\n\r\n/**\r\n * Error info from aad request\r\n */\r\nexport type AadErrorInfo = {\r\n /**\r\n * Error string\r\n */\r\n error_string?: string;\r\n\r\n /**\r\n * Platform error code\r\n */\r\n platform_error_code?: number;\r\n\r\n /**\r\n * Primary error code\r\n */\r\n primary_error?: number;\r\n\r\n /**\r\n * Secondary error code\r\n */\r\n secondary_error?: number;\r\n};\r\n\r\n/**\r\n * The client id of our application\r\n */\r\nexport const clientId = \"d7b530a4-7680-4c23-a8bf-c52c121d2e87\";\r\n\r\n/**\r\n * The scope/resource id for enterprise One Service\r\n */\r\nexport const oneServiceScope = \"f920ab6b-8a48-4438-9255-1650179a3a0f\";","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { groupBy, identity } from \"lodash-es\";\r\n\r\nimport { PageMeasure } from \"./PerfTimeline\";\r\nimport { getExperienceMeasures } from \"./ExperienceDiagnostics\";\r\nimport { getPageTimings } from \"./PageTimings\";\r\n\r\n/** The type that encapsulates the data for a single aggregated timeline object */\r\ninterface Timeline {\r\n\r\n /** Name of the timeline */\r\n name: string,\r\n\r\n /** The data for the timeline */\r\n measures: Array\r\n}\r\n\r\n/** Describes a single Process ID */\r\ninterface PID {\r\n /** The pid value */\r\n pid: number;\r\n}\r\n\r\n/** Type for easily looking up if a given timeline should be considered async */\r\ninterface AsyncTimelineGroups {\r\n /** The incrementing async PID */\r\n nextPID: PID,\r\n\r\n /** The async PID for the given timeline */\r\n [timelineName: string]: PID\r\n}\r\n\r\n/**\r\n * Calculates and returns the JSON that can be used in the chrome://tracing tool to render an\r\n * experience-centric perf timeline for various tracked page measurements in the pageMeasures object.\r\n * See https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview# for more details.\r\n *\r\n * @returns Array object with chrome trace event data that can be serialized and saved to a JSON file\r\n * to be loaded inside the chrome://tracing tool.\r\n */\r\nexport function getAppPerfTrace(): Array {\r\n\r\n // create a shallow copy since we don't want to mutate the original data from the page object\r\n const measures: Array = [];\r\n\r\n const asyncExperiences = {\r\n\r\n // Web-Worker\r\n \"WW\": { pid: 0 },\r\n\r\n // Config resolver on the render thread\r\n \"Resolver\": { pid: 1 },\r\n\r\n // Various resource timing categories.\r\n \"Ads\": { pid: 2 },\r\n \"Telemetry\": { pid: 3 },\r\n \"Content Preview\": { pid: 4 },\r\n \"Images\": { pid: 5 },\r\n \"JS\": { pid: 6 },\r\n \"Configs\": { pid: 7 },\r\n \"Services\": { pid: 8 },\r\n\r\n // The async process ID counter, which will be used to group similar timelines under virtual process IDs to\r\n // identify and group a list of related timelines. The timeline groups will render in order of smallest to\r\n // larges process ID in the chrome trace.\r\n nextPID: { pid: 20 }\r\n };\r\n\r\n // this is the process ID which will identify the main timeline (that renders last in the tool)\r\n const defaultPID = 100;\r\n\r\n // merge resource timings\r\n mergeResourceTimings(measures, asyncExperiences);\r\n\r\n // merge experience timeline measures.\r\n mergePageMeasures(measures, getExperienceMeasures(), asyncExperiences);\r\n\r\n // merge other page timings\r\n const pageTimings = { ...getPageTimings() };\r\n mergePageTimings(measures, pageTimings, asyncExperiences, /^WW\\./, \"WW\");\r\n\r\n // merge timings from window._appTimings object if it exists (used to get timeline measurements\r\n // out of band from non-typescript enabled code)\r\n const appTimings = { ...(window._appTimings || {}) };\r\n mergePageTimings(measures, appTimings, asyncExperiences, /.*/);\r\n\r\n // build chrome trace object\r\n const chromeTrace = [];\r\n\r\n // zero start instance marker to indicate nav start\r\n chromeTrace.push(chromeInstantMarker(\"Global\", \"NavStart\", defaultPID, 0, \"g\"));\r\n\r\n // Other well known instance markers\r\n Object.keys(pageTimings)\r\n .filter(name => name.match(/TT/))\r\n .sort((key1, key2) => pageTimings[key1] - pageTimings[key2])\r\n .forEach(name =>\r\n chromeTrace.push(chromeInstantMarker(\"Global\", name, defaultPID, pageTimings[name], \"g\"))\r\n );\r\n\r\n // web-worker instant markers\r\n Object.keys(pageTimings)\r\n .filter(name => name.match(/^WW\\./i))\r\n .sort((key1, key2) => pageTimings[key1] - pageTimings[key2])\r\n .forEach(name =>\r\n chromeTrace.push(chromeInstantMarker(\"WW\", name, asyncExperiences[\"WW\"].pid, pageTimings[name], \"p\"))\r\n );\r\n\r\n // Main process name metadata\r\n chromeTrace.push(chromeMetadata(\"process_name\", defaultPID, { name: \"Main\" }));\r\n chromeTrace.push(chromeMetadata(\"process_sort_index\", defaultPID, { sort_index: defaultPID }));\r\n\r\n // async timelines\r\n calculateTimelines(measures, true)\r\n .forEach((timeline, timelineIndex) => {\r\n\r\n const { pid } = asyncExperiences[timeline.name];\r\n\r\n // for async timelines, we need to create a separate process so the individual\r\n // measurements can start on their own line as async events should\r\n timeline.measures.forEach((measure, measureIndex) => {\r\n\r\n const { timelineName, measureName, from, to } = measure;\r\n const measureIndexPrefix = (\"000\" + measureIndex).substr(-3, 3);\r\n const name = `${measureIndexPrefix}-${measureName}`;\r\n\r\n // async begin/end\r\n chromeTrace.push(...chromeAsyncMeasure(timelineName, name, pid, timelineIndex, measureIndex, from, to));\r\n });\r\n\r\n // since we're creating a new process id for async experiences, put the name metadata for the process\r\n chromeTrace.push(chromeMetadata(\"process_name\", pid, { name: timeline.name }));\r\n chromeTrace.push(chromeMetadata(\"process_sort_index\", pid, { sort_index: pid }));\r\n chromeTrace.push(chromeMetadata(\"thread_name\", pid, { name: timeline.name }, timelineIndex));\r\n chromeTrace.push(chromeMetadata(\"thread_sort_index\", pid, { sort_index: timelineIndex }, timelineIndex));\r\n });\r\n\r\n // sync timelines\r\n calculateTimelines(measures, false)\r\n .forEach((timeline, timelineIndex) => {\r\n\r\n const pid = defaultPID;\r\n\r\n timeline.measures.forEach(measure => {\r\n const { timelineName, measureName, from, to } = measure;\r\n chromeTrace.push(chromeSyncMeasure(timelineName, measureName, pid, timelineIndex, from, to));\r\n });\r\n\r\n chromeTrace.push(chromeMetadata(\"thread_name\", pid, { name: timeline.name }, timelineIndex));\r\n chromeTrace.push(chromeMetadata(\"thread_sort_index\", pid, { sort_index: timelineIndex }, timelineIndex));\r\n });\r\n\r\n return chromeTrace;\r\n}\r\n\r\n/**\r\n * Creates a chrome metadata entry object\r\n */\r\nfunction chromeMetadata(metadataType: string, pid: number, args: object, threadId?: number): object {\r\n\r\n const metadata: any = {\r\n name: metadataType,\r\n ph: \"M\",\r\n pid,\r\n args\r\n };\r\n\r\n if (threadId != null) {\r\n metadata.tid = threadId;\r\n }\r\n\r\n return metadata;\r\n}\r\n\r\n/**\r\n * Returns two markers that signifiy the measurement of an asynchronous event\r\n */\r\nfunction chromeAsyncMeasure(category: string, name: string, pid: number, threadId: number, id: number, fromMs: number, toMs: number, showInParentThread?: boolean): Array {\r\n return [\r\n chromeMarker(category, name, showInParentThread ? \"B\" : \"b\", pid, threadId, fromMs, { id }),\r\n chromeMarker(category, name, showInParentThread ? \"E\" : \"e\", pid, threadId, toMs, { id })\r\n ];\r\n}\r\n\r\n/**\r\n * Returns two markers that signifiy the measurement of an synchronous event\r\n */\r\nfunction chromeSyncMeasure(category: string, name: string, pid: number, threadId: number, fromMs: number, toMs: number): object {\r\n return chromeMarker(category, name, \"X\", pid, threadId, fromMs, { dur: (toMs - fromMs) * 1000 });\r\n}\r\n\r\n/**\r\n * Returns an instance marker\r\n */\r\nfunction chromeInstantMarker(category: string, name: string, pid: number, timeStampMs: number, type: string): object {\r\n return chromeMarker(category, name, \"i\", pid, null, timeStampMs, { s: type });\r\n}\r\n\r\n/**\r\n * Creates a generic Chrome marker entry\r\n */\r\nfunction chromeMarker(category: string, name: string, type: string, pid: number, threadId: number = null, timeStampMs: number, auxData: any): object {\r\n const marker: any = {\r\n cat: category,\r\n name,\r\n ph: type,\r\n pid,\r\n tid: threadId,\r\n ts: timeStampMs * 1000,\r\n ...auxData\r\n };\r\n\r\n if (threadId != null) {\r\n marker.tid = threadId;\r\n }\r\n\r\n return marker;\r\n}\r\n\r\n/**\r\n * Iterates through the given measure data, parses, groups timeline data and creates\r\n * a sorted array of {Timeline} objects to render in the Chrome trace\r\n *\r\n * @param measures - the measure data object to which to append new measurements.\r\n * @returns the array of aggregated, sorted {Timeline} objects.\r\n */\r\nfunction calculateTimelines(measures: Array, async: boolean): Array {\r\n\r\n // group info objects by experience name\r\n const timelineGroups = groupBy(\r\n measures.filter(measure => !!measure.async === async),\r\n info => info.timelineName\r\n );\r\n\r\n // create a list of sub-timelines where each sub-timeline is sorted by metric value\r\n const timelineList: Array = [];\r\n let maxValue = 0;\r\n\r\n Object.keys(timelineGroups).forEach(groupName => {\r\n\r\n // sort each timeline by start metric value\r\n const timeline = timelineGroups[groupName].sort(\r\n (info1, info2) => info1.from - info2.from\r\n );\r\n\r\n // get the running max value from the last metric on each sorted timeline\r\n maxValue = Math.max(maxValue, timeline[timeline.length - 1].to);\r\n\r\n timelineList.push({\r\n name: groupName,\r\n measures: timeline\r\n });\r\n });\r\n\r\n // sort the list of timelines by first appearing metric for each timeline.\r\n // This is the order we will render the timeline view from top to bottom,\r\n // so that each line represents a single experience's timeline.\r\n return timelineList.sort(\r\n (timeline1, timeline2) => timeline1.measures[0].from - timeline2.measures[0].from\r\n );\r\n}\r\n\r\n/**\r\n * Attempts to map measures from the given object bag that contains related start/end markers\r\n * and adds to the given measures array.\r\n * @param measures - the measure data object to which to append new measurements.\r\n * @param pageTimings - the page timings object from which to parse data from.\r\n * @param asyncExperiences - the async info object containing the currently allocated PID info\r\n * @param matchRegex - regex to use to filter the metric names.\r\n * @param timelineName - Optional name to use for the timeline. If not specified the measure name will\r\n * be parsed to attempt to derive the timeline name dynamically.\r\n */\r\nfunction mergePageTimings(\r\n measures: Array,\r\n pageTimings: object,\r\n asyncExperiences: AsyncTimelineGroups,\r\n matchRegex: RegExp,\r\n timelineName?: string\r\n): void {\r\n\r\n // work out other WW markers\r\n const startSuffixRegex = /\\-?[Ss]tart$/;\r\n\r\n // we have a range of start/end marker styles in WW code :-/\r\n const endSuffixLookup = {\r\n \"-Start\": \"-End\",\r\n \"-start\": \"-end\",\r\n \"Start\": \"End\",\r\n \"start\": \"end\"\r\n };\r\n\r\n const processedKeysToRemove = [];\r\n\r\n Object.keys(pageTimings)\r\n .filter(key => key.match(matchRegex))\r\n .forEach(key => {\r\n\r\n const startSuffixMatch = key.match(startSuffixRegex);\r\n if (!startSuffixMatch) {\r\n return;\r\n }\r\n\r\n let measureName = key.replace(startSuffixRegex, \"\");\r\n const endKey = `${measureName}${endSuffixLookup[startSuffixMatch[0]]}`;\r\n const endValue = startSuffixMatch && pageTimings[endKey];\r\n\r\n if (!endValue) {\r\n return;\r\n }\r\n\r\n processedKeysToRemove.push(key);\r\n processedKeysToRemove.push(endKey);\r\n\r\n let thisTimelineName = timelineName;\r\n\r\n // if we're not given an explicit timeline name, then see if we can try to derive the\r\n // timeline name from the measurement (i.e., see if the measure name is formatted as\r\n // [timeline name].[measure name]), and if so, use that instead. This is useful for aggregating\r\n // related timeline measures across code that use the PerfTimeline class as well as the global\r\n // window._appTimings object to generate a unified timeline.\r\n if (!thisTimelineName) {\r\n const prefixSuffixMatch = measureName.match(/(.+)\\.(.+)/);\r\n if (prefixSuffixMatch) {\r\n thisTimelineName = prefixSuffixMatch[1];\r\n measureName = prefixSuffixMatch[2];\r\n } else {\r\n // no explicit timeline name, and no timeline name could be derived from the measure name\r\n return;\r\n }\r\n }\r\n\r\n measures.push({\r\n async: !!asyncExperiences[thisTimelineName],\r\n timelineName: thisTimelineName,\r\n measureName,\r\n from: pageTimings[key],\r\n to: endValue\r\n });\r\n });\r\n\r\n // remove the keys we used for detecting start/end from the measures so we don't attempt\r\n // to process them again for something else\r\n for (const keyToRemove of processedKeysToRemove) {\r\n delete pageTimings[keyToRemove];\r\n }\r\n}\r\n\r\n/**\r\n * Parses various resource timings that are of interest and merges into the measure data object\r\n * @param measures - the destination array into which we will add the resource timings.\r\n * @param asyncExperiences - the async info object containing the currently allocated PID info\r\n */\r\nfunction mergeResourceTimings(measures: Array, asyncExperiences: AsyncTimelineGroups): void {\r\n\r\n // interesting groups from resource timings.\r\n // IMPORTANT!! Put from most specific to less specific, so dupes don't appear in multiple groups.\r\n let resourceGroupings = [\r\n\r\n // Ads\r\n { name: \"Ads\", regex: /(\\/srtb\\.|taboola|outbrain)/i },\r\n\r\n // Config service calls (CRS or Config)\r\n { name: \"Telemetry\", regex: /(otf\\.|\\/c\\.gif)/i },\r\n\r\n // Content preview calls.\r\n // Note: put before services to avoid capture of /content/\r\n { name: \"Content Preview\", regex: /\\/content\\/view\\/v[0-9]\\/Preview\\//i },\r\n\r\n // Content service calls (i.e., content preview)\r\n { name: \"Images\", regex: /(img-s-msn-com|\\.svg)/i },\r\n\r\n // Javascript resources.\r\n // Note: put before configs, to avoid capture of web-worker hash, which contains config stuff\r\n { name: \"JS\", regex: /\\.js/i },\r\n\r\n // Config service calls (CRS or Config)\r\n { name: \"Configs\", regex: /\\/config/i },\r\n\r\n // Various known service calls to 1S (i.e., feed, structure data, etc.)\r\n { name: \"Services\", regex: /(\\/service\\/|apiKey|\\/getappanoncookie|content)/i }\r\n ];\r\n\r\n let nonZeroResources = performance.getEntriesByType(\"resource\")\r\n .filter(entry => entry.duration > 0);\r\n\r\n resourceGroupings.forEach(resourceGroup => {\r\n\r\n // add the resource group names to the async experiences list\r\n tryCreateAsyncPID(resourceGroup.name, asyncExperiences);\r\n\r\n let remainingResources = [];\r\n\r\n nonZeroResources\r\n .filter(entry => {\r\n const match = entry.name.match(resourceGroup.regex);\r\n if (!match) {\r\n remainingResources.push(entry);\r\n }\r\n return match;\r\n })\r\n .forEach((entry, entryIndex) => {\r\n\r\n const url = new URL(entry.name);\r\n const measureName = url.pathname.length > 1\r\n ? url.pathname\r\n : url.hostname;\r\n\r\n measures.push({\r\n async: true,\r\n timelineName: resourceGroup.name,\r\n measureName: `${measureName}-${entryIndex}`,\r\n from: entry.startTime,\r\n to: entry.startTime + entry.duration\r\n });\r\n });\r\n\r\n // don't re-process the ones we already matched for a previous group.\r\n nonZeroResources = remainingResources;\r\n });\r\n}\r\n\r\n/**\r\n * Appends the given measure to the target array\r\n * @param destinationMeasures - the destination array to which to add the measures\r\n * @param sourceMeasures - the source list of measures to process and add\r\n * @param asyncExperiences - the async info object containing the currently allocated PID info\r\n * @param asyncPID - the last allocated async PID\r\n * @returns {number} The next usable async PID\r\n */\r\nfunction mergePageMeasures(\r\n destinationMeasures: Array,\r\n sourceMeasures: Array,\r\n asyncExperiences: AsyncTimelineGroups\r\n): void {\r\n\r\n sourceMeasures.forEach(measure => {\r\n const { async, timelineName } = measure;\r\n if (async) {\r\n tryCreateAsyncPID(timelineName, asyncExperiences);\r\n }\r\n destinationMeasures.push(measure);\r\n });\r\n}\r\n\r\n/**\r\n * Attempts to create a new async PID for the given timeline name if it does not already exist\r\n * @param timelineName - the name of the async timeline to allocate a new PID if it does not exist.\r\n * @param asyncExperiences - the async info object containing the currently allocated PID info\r\n * @returns {boolean} Indicating whether an async PID exists for the given timeline or not.\r\n */\r\nfunction tryCreateAsyncPID(timelineName: string, asyncExperiences: AsyncTimelineGroups): boolean {\r\n if (!asyncExperiences[timelineName]) {\r\n asyncExperiences[timelineName] = { pid: asyncExperiences.nextPID.pid++ };\r\n return true;\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { logger } from \"../logging\";\r\nimport { getAppPerfTrace } from \"./AppPerfTrace\";\r\nimport { getPageTimings } from \"./PageTimings\";\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\n\r\nconst pageTimings = getPageTimings();\r\n\r\n/**\r\n * Utility class to keep track of how many times a key has appeared in order to\r\n * get a uniquely qualified name back to be used in a dictionary.\r\n */\r\nclass KeyCounter {\r\n\r\n /** Lookup of counts for the given key */\r\n private timelineCount: { [name: string]: number } = {};\r\n\r\n /** Gets the qualified key name */\r\n public qualifyKey(timelineName: string): string {\r\n\r\n // get the previous count\r\n const count = this.getCount(timelineName);\r\n\r\n // if we've called it previously append the count as suffix\r\n // to identify it uniquely.\r\n if (count <= 1) {\r\n return timelineName;\r\n }\r\n\r\n return timelineName + count;\r\n }\r\n\r\n /** Resets the counter state to initial values */\r\n public reset(): void {\r\n this.timelineCount = {};\r\n }\r\n\r\n /** Gets the key's appearence count */\r\n private getCount(timelineName: string): number {\r\n\r\n // get the previous count\r\n const count = this.timelineCount[timelineName] || 0;\r\n\r\n // update the new count\r\n return this.timelineCount[timelineName] = count + 1;\r\n }\r\n}\r\n\r\n/** Type info of a single page measure in the window._pageMeasures object */\r\nexport type PageMeasure = {\r\n\r\n /** Name of the timeline */\r\n timelineName: string;\r\n\r\n /** Name of the metric */\r\n measureName: string;\r\n\r\n /** Flag that indicates whether this measure is an async measure */\r\n async?: boolean;\r\n\r\n /** The start time of the measure */\r\n from: number;\r\n\r\n /** The end time of the measure */\r\n to: number;\r\n};\r\n\r\n/**\r\n * Unique key qualifier for distinctly identifying instances of perf timelines\r\n * across multiple instances of the same or different experience types.\r\n * For example, ContentPreview, ContentPreview2, ContentPreview3, etc.\r\n */\r\nconst timelineKeyCount = new KeyCounter();\r\n\r\n/** Suffix for start markers */\r\nconst startSuffix = \"-start\";\r\n\r\n/** Suffix for end markers */\r\nconst endSuffix = \"-end\";\r\n\r\n/**\r\n * This class can be used to aggregate a list of perf markers and their transitions.\r\n */\r\nexport class PerfTimeline {\r\n\r\n /**\r\n * Unique key qualifier for metric names that appear multiple times.\r\n * For example, render, render2, render3, etc.\r\n */\r\n private readonly markerCount: KeyCounter = new KeyCounter();\r\n\r\n /**\r\n * List of in-memory logged markers for this perf-timeline object\r\n */\r\n private readonly measures: Array> = [];\r\n\r\n /**\r\n * Constructor of a {PerfTimeline} instance\r\n * @param timelineName - the name of the perf timeline. Note that if you don't know the name\r\n * of a perf timeline at construction time, it can later be renamed to a known name later via\r\n * the 'rename' method.\r\n * @param instanceId - this specific instance's ID. Used during a renaming operation to idenfity any previous isntance.\r\n * @param addPerfMarks - Flag to indicate whether to log perf marks with the native performance API.\r\n * @param addPageTimings - Flag to indicate whether to log the perf marks into the _pageTimings object.\r\n * @param async - Flag to mark this timeline as an async timeline, so by default all measures under\r\n * this timeline will show under a new process line.\r\n */\r\n protected constructor(\r\n public timelineName: string,\r\n public readonly instanceId: string,\r\n private readonly addPerfMarks: boolean,\r\n private readonly addPageTimings: boolean,\r\n private readonly async?: boolean\r\n ) {\r\n this.timelineName = timelineKeyCount.qualifyKey(this.timelineName);\r\n }\r\n\r\n /**\r\n * Helper to construct a {PerfTimeline} instance\r\n * @param timelineName - the name of the perf timeline. Note that if you don't know the name\r\n * of a perf timeline at construction time, it can later be renamed to a known name later via\r\n * the 'rename' method.\r\n * @param instanceId - this specific instance's ID. Used during a renaming operation to idenfity any previous isntance.\r\n * @param addPerfMarks - Flag to indicate whether to log perf marks with the native performance API.\r\n * @param addPageTimings - Flag to indicate whether to log the perf marks into the _pageTimings object.\r\n * @param async - Flag to mark this timeline as an async timeline, so by default all measures under\r\n * this timeline will show under a new process line.\r\n */\r\n public static create(\r\n timelineName: string,\r\n instanceId: string,\r\n addPerfMarks: boolean = false,\r\n addPageTimings: boolean = false,\r\n async?: boolean\r\n ): PerfTimeline {\r\n return new PerfTimeline(timelineName, instanceId, addPerfMarks, addPageTimings, async);\r\n }\r\n\r\n /**\r\n * Renames this instances of the timeline to the new given name.\r\n * This is useful when the timeline name is not known until after some asynchronous operation is completed,\r\n * but the measuring operation required to be started before the name was known.\r\n * @param timelineName - the new name of the timeline.\r\n */\r\n public rename(timelineName: string): void {\r\n\r\n if (this.timelineName === timelineName) {\r\n return;\r\n }\r\n\r\n if (this.addPageTimings) {\r\n // if we're adding page timings, then make sure we delete the measures under the old name and add the new ones\r\n this.measures.forEach(measure => {\r\n const oldMeasureName = this.qualifyMeasureName(measure.measureName);\r\n delete pageTimings[oldMeasureName + startSuffix];\r\n delete pageTimings[oldMeasureName];\r\n });\r\n }\r\n\r\n this.timelineName = timelineName;\r\n\r\n if (this.addPageTimings) {\r\n // add back the page timings under the new timeline name\r\n this.measures.forEach(measure => {\r\n const newMeasureName = this.qualifyMeasureName(measure.measureName);\r\n pageTimings[newMeasureName + startSuffix] = measure.from;\r\n pageTimings[newMeasureName] = measure.to - measure.from;\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Marks the start of a timeline measurement.\r\n * @param coreMarkerName - the name of the core marker. This value is usually invariant\r\n * from instance to instance (i.e., init, config, render)\r\n * @param dynamicMeasureName - the optional additional identifying name to give for the measure.\r\n * This value can be used to identify dynamic values across instances. For example the\r\n * HREF of the config. This can also later be updated to a new name when calling the 'endMeasure'\r\n * method.\r\n * @param async - flag to indicate whether this is an async measure or not.\r\n * @returns An object with the following properties:\r\n * - endMeasure - method that should be used to mark the end the measure.\r\n */\r\n public startMeasure(coreMarkerName: string, dynamicMeasureName?: string, async?: boolean): { endMeasure: (updatedDynamicMeasureName?: string) => void } {\r\n\r\n const startTime = performance.now();\r\n\r\n const timelineNameAtStart = this.timelineName;\r\n let measureNameCore = this.formatMeasureName(coreMarkerName, dynamicMeasureName);\r\n let measureName = this.qualifyMeasureName(measureNameCore);\r\n\r\n let startMarkerName = measureName + startSuffix;\r\n this.singleMark(startMarkerName);\r\n\r\n if (this.addPageTimings) {\r\n pageTimings[startMarkerName] = startTime;\r\n }\r\n\r\n return {\r\n /**\r\n * Ends the given measure we started\r\n */\r\n // tslint:disable-next-line:no-shadowed-variable\r\n endMeasure: (updatedDynamicMeasureName?: string) => {\r\n\r\n const endTime = performance.now();\r\n\r\n // flag to indicate whether we need to re-qualify the measure name based on frequency. Note that we only\r\n // set this to true if the timeline name has changed since start, or we have a new dynamic name at the end.\r\n const requalifyMeasureName = updatedDynamicMeasureName\r\n || (timelineNameAtStart !== this.timelineName);\r\n\r\n if (requalifyMeasureName) {\r\n // if by the time we're ending the measure, we have a new dynamic name for the measurement, use that as the final measure name.\r\n measureNameCore = this.formatMeasureName(coreMarkerName, updatedDynamicMeasureName);\r\n measureName = this.qualifyMeasureName(measureNameCore);\r\n }\r\n\r\n const endMarkerName = measureName + endSuffix;\r\n\r\n this.singleMark(endMarkerName);\r\n this.measure(measureName, startMarkerName, endMarkerName);\r\n\r\n // Note we only save the partial metric without the timeline name, so we can use the final timeline name\r\n // if any rename operations happen while initial measurements have started without the final timeline name\r\n this.measures.push({\r\n measureName: measureNameCore,\r\n async: (async != null) ? async : this.async,\r\n from: startTime,\r\n to: endTime\r\n });\r\n\r\n if (this.addPageTimings) {\r\n pageTimings[measureName] = endTime - startTime;\r\n }\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * Returns the list of page measures for this timeline object\r\n * @returns {Array} containing the fully qualified list of metric names for this perf timeline.\r\n */\r\n public getPageMeasures(): Array {\r\n return this.measures.map(measure => ({\r\n ...measure,\r\n timelineName: this.timelineName\r\n }));\r\n }\r\n\r\n /**\r\n * Instruments the start/begin for the given function with a given binding context\r\n * @param funcName - the identifying name of the function\r\n * @param func - the function instance to measure\r\n * @param bindingContext - the optional context from which to invoke the function\r\n * @returns the instrumented function that will track the start/end of the given function.\r\n */\r\n public instrumentFunc(funcName: string, func: TFunc, bindingContext?: Object): TFunc {\r\n\r\n const _this = this;\r\n\r\n let wrapper = function (): any {\r\n const endMeasure = _this.startMeasure(funcName).endMeasure;\r\n try {\r\n return func.apply(bindingContext, arguments);\r\n } finally {\r\n endMeasure();\r\n }\r\n };\r\n\r\n return wrapper as any as TFunc;\r\n }\r\n\r\n /**\r\n * Instruments the start/begin for the given async-style function\r\n * @param promiseName - the identifying name of the promise\r\n * @param getPromise - the promise getter that returns the promise to measure. This is needed\r\n * so that the start measurement can occur before the promise starts executing.\r\n * @param async - flag to indicate whether to measure this promise as an async timeline\r\n * or a synchronous one. Please note that if you specify this as true, and other measurements\r\n * in the timeline are synchronous, the async measurements will appear as a separate timeline\r\n * and will not be next to the synchronous one. If unsure, leave undefined.\r\n * @returns the wrapped promise that tracks the start/end of the promise execution.\r\n */\r\n public async instrumentPromise(promiseName: string, getPromise: () => Promise, async?: boolean): Promise {\r\n\r\n const endMeasure = this.startMeasure(promiseName, null, async).endMeasure;\r\n try {\r\n return await getPromise();\r\n } finally {\r\n endMeasure();\r\n }\r\n }\r\n\r\n /**\r\n * Prefixes the given measure name with the current timeline name\r\n * @param measureName - the measure name to qualify\r\n * @returns the timeline name prefixed measure name.\r\n */\r\n private qualifyMeasureName(measureName: string): string {\r\n return `${this.timelineName}-${measureName}`;\r\n }\r\n\r\n /**\r\n * Returns the formatted measure name with it's constiuent parts\r\n * @param coreMeasureName - the core marker name\r\n * @param dynamicMeasureName - optional dynamic measure name\r\n * @returns the formatted marker name\r\n */\r\n private formatMeasureName(coreMeasureName: string, dynamicMeasureName?: string): string {\r\n const dynamicMeasureSuffix = dynamicMeasureName ? (\"-\" + dynamicMeasureName) : \"\";\r\n return this.markerCount.qualifyKey(`${coreMeasureName}${dynamicMeasureSuffix}`);\r\n }\r\n\r\n /**\r\n * Helper to add a single mark with the performance API\r\n * @param markerName - the name of the marker to add.\r\n */\r\n private singleMark(markerName: string): void {\r\n if (this.addPerfMarks) {\r\n performance.mark(markerName);\r\n }\r\n }\r\n\r\n /**\r\n * Helper to calculate a performance measurement against the performance API\r\n * @param measureName - the name of the measure\r\n * @param startMarker - the name of the start marker\r\n * @param endMarker - the name of the end marker\r\n */\r\n private measure(measureName: string, startMarker: string, endMarker: string): void {\r\n if (this.addPerfMarks) {\r\n try {\r\n // this can throw if start/end markers were not available for some reason\r\n performance.measure(measureName, startMarker, endMarker);\r\n } catch (ex) {\r\n logger.logError(ex);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Test export for resetting the timeline name counter\r\n */\r\nexport function _resetTimelineKeyCounter(): void {\r\n timelineKeyCount.reset();\r\n}\r\n\r\n// Note that we're exporting this function here so that it doesn't get tree shaken out\r\n// since it's not actually referenced from any PROD code anywhere. Since the PerfTimeline class\r\n// is referenced, having the getAppPerfTrace function referenced here would end up bundling in the final bits.\r\nif (canUseDOM()) {\r\n (window)._getAppPerfTrace = getAppPerfTrace;\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { PageMeasure, PerfTimeline } from \"./PerfTimeline\";\r\nimport { canUseDOM, getLocationHref } from \"@msnews/isomorphic-util\";\r\n\r\nimport { logger } from \"../logging\";\r\n\r\n/**\r\n * In case we're tracking only specific experience types, this will contain\r\n * the keys of experiences that were requested to be tracked.\r\n */\r\nlet experiencesForPerf: { [key: string]: boolean };\r\n\r\n/**\r\n * In case we're excluding specific experiences from tracking. Useful when\r\n * we want to track all experiences, except for a few noisy ones, for example.\r\n */\r\nlet experiencesExcludedForPerf: { [key: string]: boolean };\r\n\r\n/**\r\n * Flag to indicate we want to log marks & measurements against the performance API.\r\n * By default, all marks and measurements will only happen against an in-memory object.\r\n * Note that when you enable this option, it will incur an additional overhead from using\r\n * the API. You should only use this option when you want to look at the perf trace in\r\n * the browser's F12 tools. This is not required otherwise.\r\n *\r\n * Controlled via the experPerfMark=true QSP.\r\n */\r\nlet addPerformanceMarks: boolean;\r\n\r\n/**\r\n * Flag to add any perf timeline measurements to the global _pageTimings object\r\n */\r\nlet addPageTimings: boolean;\r\n\r\n/**\r\n * Flag to indicate that we're tracking all experiences.\r\n *\r\n * Controlled via the expPerf=all QSP\r\n */\r\nlet trackAllExp: boolean;\r\n\r\n/**\r\n * Top-level flag to enable perf timeline features\r\n */\r\nlet enablePerfTimeline: boolean;\r\n\r\n/**\r\n * Dictionary containing the unique {PerfTimeline} object instances across the app.\r\n * When related measurements on the same perf timeline is required across unrelated parts\r\n * of the code, this will guarantee you're tracking those measurements under the same\r\n * perf timeline using a combination of the experience name and instance id.\r\n */\r\nlet perfTimelineInstances: { [instanceId: string]: PerfTimeline };\r\n\r\n/**\r\n * Initializes experience perf diagnostic specific state\r\n * Note: this method should not be called explicitly (other than from UTs.)\r\n * It is already called by default at the beginning of module initialization.\r\n * @param locationHref - the value of window.location.href from which to parse options\r\n */\r\nexport function initExperienceDiagnostics(locationHref: string): void {\r\n\r\n addPageTimings = false;\r\n addPerformanceMarks = false;\r\n experiencesExcludedForPerf = {};\r\n experiencesForPerf = {};\r\n perfTimelineInstances = {};\r\n trackAllExp = false;\r\n\r\n try {\r\n const searchParams = (new URL(locationHref)).searchParams;\r\n const expPerfQsp = searchParams.get(\"expPerf\");\r\n enablePerfTimeline = !!expPerfQsp;\r\n\r\n // if we weren't requested for any experience perf tracking, return early.\r\n if (!enablePerfTimeline) {\r\n return;\r\n }\r\n\r\n trackAllExp = expPerfQsp === \"all\";\r\n\r\n // if an explicit experience name list was specified, convert it to an boolean map\r\n // for efficient lookup so that we can create or avoid cration of the timeline object\r\n // for whatever experience needs instrumentation.\r\n if (!trackAllExp && expPerfQsp) {\r\n expPerfQsp.split(\",\").forEach(expName =>\r\n experiencesForPerf[expName] = true\r\n );\r\n }\r\n\r\n // parse explicit exclusions from perf timeline\r\n const expPerfSkipQsp = searchParams.get(\"expPerfSkip\");\r\n if (expPerfSkipQsp) {\r\n expPerfSkipQsp.split(\",\").forEach(expName =>\r\n experiencesExcludedForPerf[expName] = true\r\n );\r\n }\r\n\r\n addPerformanceMarks = searchParams.get(\"expPerfMarks\") === \"true\";\r\n addPageTimings = searchParams.get(\"expPerfTimings\") === \"true\";\r\n\r\n } catch (e) {\r\n logger.logError(\"Error parsing URL for detecting experience diagnostic switches: \" + e);\r\n }\r\n}\r\n\r\n// initialize right away\r\n// TODO (http://osgvsowi/24596752): This needs reinitialized on each request when server side rendering\r\nif (canUseDOM()) {\r\n initExperienceDiagnostics(getLocationHref());\r\n}\r\n\r\n/**\r\n * Gets or creates a perf timeline object for the given experience instance\r\n * @param experienceName - the name of the experience for which to create the timeline\r\n * @param instanceId - the ID that will uniquely identify this timeline across multiple instances.\r\n * @param async - Optional flag to indicate the default tracing mode for this timeline.\r\n * Specifying true will render the measures under its own process id in the app trace.\r\n * Useful if the timeline will contain many async operations that frequently overlap with each other.\r\n * Note that this value can be overriden when taking an individual measure as well.\r\n */\r\nexport function tryGetPerfTimeline(experienceName: string, instanceId: string, async?: boolean): PerfTimeline {\r\n\r\n if (!shouldTrackPerfTimeline(experienceName)) {\r\n return;\r\n }\r\n\r\n const instanceKey = getInstanceKeyCore(experienceName, instanceId);\r\n\r\n const perfTimeline = perfTimelineInstances[instanceKey];\r\n if (perfTimeline) {\r\n return perfTimeline;\r\n }\r\n\r\n return perfTimelineInstances[instanceKey] = PerfTimeline.create(\r\n experienceName,\r\n instanceId,\r\n addPerformanceMarks,\r\n addPageTimings,\r\n async\r\n );\r\n}\r\n\r\n/**\r\n * Renames the given perf timeline object and moves the lookup dictionary reference under the new key\r\n * @param perfTimeline - the perf timeline to rename\r\n * @param newExperienceName - the new name for the perf timeline\r\n */\r\nexport function renamePerfTimeline(perfTimeline: PerfTimeline, newExperienceName: string): void {\r\n\r\n const oldInstanceKey = getInstanceKey(perfTimeline);\r\n\r\n if (perfTimelineInstances[oldInstanceKey] !== perfTimeline) {\r\n logger.logError(`Attempted to rename a perf timeline object with mismatching instance key ${oldInstanceKey}`);\r\n return;\r\n }\r\n\r\n // rename the perf timeline to the new name\r\n perfTimeline.rename(newExperienceName);\r\n\r\n // delete the old reference\r\n delete perfTimelineInstances[oldInstanceKey];\r\n\r\n // ...and add the new instance under the new key\r\n const newInstanceKey = getInstanceKey(perfTimeline);\r\n perfTimelineInstances[newInstanceKey] = perfTimeline;\r\n}\r\n\r\n/**\r\n * Returns the list of page measures from all the perf timeline objects being tracked\r\n */\r\nexport function getExperienceMeasures(): Array {\r\n const pageMeasures: Array = [];\r\n Object.keys(perfTimelineInstances).forEach(instanceKey =>\r\n pageMeasures.push(...perfTimelineInstances[instanceKey].getPageMeasures())\r\n );\r\n return pageMeasures;\r\n}\r\n\r\n/**\r\n * Helper to check whether we should track perf timeline for the given experience\r\n * @param experienceName - the name of the experience to check\r\n * @returns {boolean} indicating whether the given experience should be tracked for perf\r\n */\r\nfunction shouldTrackPerfTimeline(experienceName: string): boolean {\r\n return enablePerfTimeline\r\n && !experiencesExcludedForPerf[experienceName]\r\n && (trackAllExp || experiencesForPerf[experienceName]);\r\n}\r\n\r\n/**\r\n * Gets the instance key to store the experience timeline\r\n * @param perfTimeline - the timeline object from which to get the instance key.\r\n * @returns the cache key that represents the location to which to store the perf timeline.\r\n */\r\nfunction getInstanceKey(perfTimeline: PerfTimeline): string {\r\n const { timelineName, instanceId } = perfTimeline;\r\n return getInstanceKeyCore(timelineName, instanceId);\r\n}\r\n\r\n/**\r\n * Gets the instance key to store the experience timeline\r\n * @param experienceName - the name of the experience\r\n * @param instanceId - the instance ID for the perf timeline.\r\n * @returns the cache key that represents the location to which to store the perf timeline.\r\n */\r\nfunction getInstanceKeyCore(experienceName: string, instanceId: string): string {\r\n return `${experienceName}-${instanceId || \"0\"}`;\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * An enumeration of global / fixed connector namespaces\r\n * Only name spaces that are constant (i.e. not instanced) for the entire SPA lifetime should be listed here\r\n * NOTE: Keep this list alphabetical\r\n */\r\nexport enum ConnectorNamespaces {\r\n AdsManager = \"AdsManager\",\r\n BingImageData = \"BingImageData\",\r\n CategoryData = \"CategoryData\",\r\n ChromiumPageSettings = \"ChromiumPageSettings\",\r\n CoachmarkData = \"CoachmarkData\",\r\n DisplayAdsManager = \"DisplayAdsManager\",\r\n ExperienceTrackerData = \"ExperienceTrackerData\",\r\n ExperienceTrackerEdgeData = \"ExperienceTrackerEdgeData\",\r\n ExperienceTrackerEdgeNextData = \"ExperienceTrackerEdgeNextData\",\r\n ExperienceTrackerFirstPartyData = \"ExperienceTrackerFirstPartyData\",\r\n ExperienceTrackerMicrosoftNewsData = \"ExperienceTrackerMicrosoftNewsData\",\r\n ExperienceTrackerHubData = \"ExperienceTrackerHubData\",\r\n ExperienceTrackerOfficeData = \"ExperienceOfficeData\",\r\n ExperienceTrackerViewsData = \"ExperienceTrackerViewsData\",\r\n FeedbackData = \"FeedbackData\",\r\n IrisData = \"IrisData\",\r\n LayoutPreferenceData = \"LayoutPreferenceData\",\r\n MsccCookieBannerData = \"MsccCookieBannerData\",\r\n MilestoneData = \"MilestoneData\",\r\n MsNewsPageSettings = \"MsNewsPageSettings\",\r\n NavigationData = \"NavigationData\",\r\n OfficeSharedData = \"OfficeSharedData\",\r\n OneServiceContent = \"OneServiceContent\",\r\n PageClickTrackerData = \"PageClickTrackerData\",\r\n PageSettingsData = \"EdgePageSettings\",\r\n PageLayout = \"PageLayout\",\r\n PlacementManager = \"PlacementManager\",\r\n PoweredByData = \"PoweredByData\",\r\n Preload = \"Preload\",\r\n SharedState = \"SharedState\",\r\n Telemetry = \"TelemetryData\",\r\n TelemetryEdgeChromium = \"TelemetryDataEdgeChromium\",\r\n TopicData = \"TopicData\",\r\n VerticalPropertyData = \"VerticalPropertyData\",\r\n VideoDataManager = \"VideoDataManager\",\r\n WeatherData = \"WeatherData\"\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n ITrackInfo,\r\n KeyValueArray,\r\n KeyValuePair,\r\n Utility,\r\n getAppEnvironment,\r\n getHeadData,\r\n oneServiceQueryStringKeys\r\n} from \"@msnews/core\";\r\nimport { aadTokenQsKey, aadTokenQsVal, useEnterpriseCompliance } from \"@msnews/auth\";\r\n\r\nimport { isString } from \"lodash-es\";\r\n\r\n/**\r\n * A namespace that provides OneService utility functionality\r\n */\r\nexport namespace OneServiceUtility {\r\n\r\n /**\r\n * Authentication ticket type - Header value required by back-end service\r\n * Specifies what type of authentication to do\r\n */\r\n export const authenticationTicketType = \"10\";\r\n\r\n /**\r\n * Header name that holds which ANON cookie to use\r\n */\r\n export const signedInCookieNameHeader = \"signedInCookieName\";\r\n\r\n /**\r\n * Header name that holds the user-location value.\r\n */\r\n export const userLocationHeader = \"user-location\";\r\n\r\n /**\r\n * The api-key we'll be sending to OneService.\r\n */\r\n export const apiKey = \"0QfOX3Vn51YCzitbLaRkTTBadtWpgTN8NZLW0C1SEM\";\r\n\r\n /**\r\n * Executes a callback on completing of a service request\r\n *\r\n * @param {() => Promise} serviceRequest - The service request\r\n * @param {() => void} callbackMethod - The callback method\r\n * @return {Promise} - A promise of the service response\r\n */\r\n export async function serviceRequestOnComplete(serviceRequest: () => Promise, callbackMethod: () => void): Promise {\r\n try {\r\n const result = await serviceRequest();\r\n callbackMethod();\r\n\r\n return result;\r\n } catch (error) {\r\n callbackMethod();\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Gets common parameters used in service requests to OneService, when there is no personalization involved\r\n * @param {string} userId - The user id for the request\r\n * @param {string} ocidSpecifier - The OCID\r\n * @param {string} addPageInfoToOcid - If true, page_product and page_type are added to the ocid. Defaults to true\r\n * @returns {KeyValueArray}\r\n */\r\n export function getOneServiceParamsWithoutAuth(userId: string = null, ocidSpecifier: string, addPageInfoToOcid: boolean = true): KeyValueArray {\r\n const appEnvironment = getAppEnvironment();\r\n const params = [\r\n {\r\n key: oneServiceQueryStringKeys.apiKey,\r\n value: apiKey\r\n },\r\n {\r\n // TODO Bug 22266910: clarify use of activityId vs rid in this spot\r\n key: oneServiceQueryStringKeys.activityId,\r\n value: appEnvironment.ActivityId\r\n },\r\n {\r\n key: oneServiceQueryStringKeys.ocid,\r\n value: addPageInfoToOcid ? getOneServiceOCID(appEnvironment.TrackInfo, ocidSpecifier) : ocidSpecifier\r\n },\r\n {\r\n key: oneServiceQueryStringKeys.market,\r\n value: appEnvironment.CurrentMarket\r\n }\r\n ];\r\n\r\n // 21527208 - remove this after upgrading experiences to use shared lib.\r\n if (userId) {\r\n params.push({\r\n key: oneServiceQueryStringKeys.user,\r\n value: userId\r\n });\r\n }\r\n\r\n let runningExperiments = getHeadData().CurrentFlights;\r\n if (runningExperiments) {\r\n params.push({\r\n key: oneServiceQueryStringKeys.fdhead,\r\n value: runningExperiments\r\n });\r\n }\r\n\r\n if (useEnterpriseCompliance()) {\r\n params.push({\r\n key: aadTokenQsKey,\r\n value: aadTokenQsVal\r\n });\r\n }\r\n\r\n return params;\r\n }\r\n\r\n /**\r\n * Gets common parameters used in service requests to OneService,\r\n * plus authentication params in the form of the sign in cookie name\r\n * Note: This should only be called if the user is known to be signed in, else use getOneServiceParamsWithoutAuth\r\n *\r\n * @export\r\n * @param {string} userId - The user id for the request\r\n * @param {string} ocidSpecifier - The OCID\r\n * @param {string} addPageInfoToOcid - If true, page_product and page_type are added to the ocid. Defaults to true\r\n * @returns {KeyValueArray}\r\n */\r\n export function getOneServiceParamsWithAuth(userId: string = null, ocidSpecifier: string, addPageInfoToOcid: boolean = true): KeyValueArray {\r\n const appEnvironment = getAppEnvironment();\r\n const authCookieName: string = appEnvironment.AuthCookieName as string;\r\n let params = [...getOneServiceParamsWithoutAuth(userId, ocidSpecifier, addPageInfoToOcid)];\r\n if (authCookieName) {\r\n params.push({\r\n key: oneServiceQueryStringKeys.signInCookieName, // sign-in cookie name\r\n value: authCookieName.toUpperCase()\r\n });\r\n }\r\n\r\n return params;\r\n }\r\n\r\n /**\r\n * Gets common headers used in service requests to OneService\r\n *\r\n * @export\r\n * @returns {HeadersInit}\r\n */\r\n export function getOneServiceHeaders(): HeadersInit {\r\n const appEnvironment = getAppEnvironment();\r\n const headers = {};\r\n\r\n const aadToken = useEnterpriseCompliance() && appEnvironment.AadData && appEnvironment.AadData.token;\r\n if (aadToken) {\r\n headers[\"Authorization\"] = `Bearer ${aadToken}`;\r\n }\r\n\r\n return headers;\r\n }\r\n\r\n /**\r\n * Gets the location query string parameters\r\n */\r\n export function getLocationParams(): KeyValuePair {\r\n const appEnvironment = getAppEnvironment();\r\n const latitude = appEnvironment.Latitude;\r\n const longitude = appEnvironment.Longitude;\r\n\r\n if (latitude && longitude) {\r\n return { key: oneServiceQueryStringKeys.location, value: `${latitude}|${longitude}` };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Returns the OCID generated from the telemetry TrackInfo if it is valid, otherwise returns the ocid specifier\r\n * @param {ITrackInfo} trackInfo - The track info\r\n * @param {ocidSpecifier} string - The OCID\r\n * @returns {string}\r\n */\r\n export function getOneServiceOCID(trackInfo: ITrackInfo, ocidSpecifier: string): string {\r\n if (Utility.isNonNullObject(trackInfo) &&\r\n Utility.isNonNullObject(trackInfo.sitePage) &&\r\n isString(trackInfo.sitePage.page_product) &&\r\n isString(trackInfo.sitePage.page_type)) {\r\n return trackInfo.sitePage.page_product + \"-\" + trackInfo.sitePage.page_type + (ocidSpecifier ? \"-\" + ocidSpecifier : \"\");\r\n } else {\r\n return ocidSpecifier;\r\n }\r\n }\r\n\r\n /**\r\n * Sets up base request data for One Service calls\r\n * @param method\r\n * @returns - RequestInit\r\n */\r\n export function getBaseRequestData(method): RequestInit {\r\n const requestObj: RequestInit = {\r\n headers: OneServiceUtility.getOneServiceHeaders(),\r\n method\r\n };\r\n\r\n return requestObj;\r\n }\r\n\r\n /**\r\n * Populates the request init and return commonParams\r\n * @param ocid -- the ocid for this request\r\n * @returns {KeyValueArray} - parameters as a key/value array\r\n */\r\n export function getCommonParams(ocid: string): KeyValueArray {\r\n if (getHeadData().UserIsSignedIn) {\r\n return this.getOneServiceParamsWithAuth(getAppEnvironment().UserId, ocid);\r\n }\r\n\r\n return this.getOneServiceParamsWithoutAuth(getAppEnvironment().UserId, ocid);\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nexport enum Market {\r\n BR = \"pt-br\",\r\n ENCA = \"en-ca\",\r\n FRCA = \"fr-ca\",\r\n FRFR = \"fr-fr\",\r\n IN = \"en-in\",\r\n ENUS = \"en-us\",\r\n ZHCN = \"zh-cn\"\r\n}","// © Microsoft Corporation. All rights reserved.\r\n/// \r\n\r\n/**\r\n * List of SVG icon types available by its key\r\n */\r\nexport const AdChoices = () => import(/* webpackChunkName: \"icon-assets-AdChoices\" */\"@svgr/webpack?-svgo!../../icons/AdChoices.svg\");\r\nexport const BingCardDefaultHotelImage = () => import(/* webpackChunkName: \"icon-assets-BingCardDefaultHotelImage\" */\"@svgr/webpack?-svgo!../../icons/BingCardDefaultHotelImage.svg\");\r\nexport const BingHotelSeePrice = () => import(/* webpackChunkName: \"icon-assets-BingHotelSeePrice\" */\"@svgr/webpack?-svgo!../../icons/BingHotelSeePrice.svg\");\r\nexport const BingLogo = () => import(/* webpackChunkName: \"icon-assets-BingLogo\" */\"@svgr/webpack?-svgo!../../icons/BingLogo.svg\");\r\nexport const BingRatingDarkStar = () => import(/* webpackChunkName: \"icon-assets-BingRatingDarkStar\" */\"@svgr/webpack?-svgo!../../icons/BingRatingDarkStar.svg\");\r\nexport const BingRatingLightStar = () => import(/* webpackChunkName: \"icon-assets-BingRatingLightStar\" */\"@svgr/webpack?-svgo!../../icons/BingRatingLightStar.svg\");\r\nexport const BingRatingDarkLightStar = () => import(/* webpackChunkName: \"icon-assets-BingRatingDarkLightStar\" */\"@svgr/webpack?-svgo!../../icons/BingRatingDarkLightStar.svg\");\r\nexport const BlowingHail = () => import(/* webpackChunkName: \"icon-assets-BlowingHail\" */\"@svgr/webpack?-svgo!../../icons/BlowingHail.svg\");\r\nexport const BlowingHailWhite = () => import(/* webpackChunkName: \"icon-assets-BlowingHailWhite\" */\"@svgr/webpack?-svgo!../../icons/BlowingHailWhite.svg\");\r\nexport const BlowingSnow = () => import(/* webpackChunkName: \"icon-assets-BlowingSnow\" */\"@svgr/webpack?-svgo!../../icons/BlowingSnow.svg\");\r\nexport const BlowingSnowWhite = () => import(/* webpackChunkName: \"icon-assets-BlowingSnowWhite\" */\"@svgr/webpack?-svgo!../../icons/BlowingSnowWhite.svg\");\r\nexport const Check = () => import(/* webpackChunkName: \"icon-assets-Check\" */\"@svgr/webpack?-svgo!../../icons/Check.svg\");\r\nexport const Chevron = () => import(/* webpackChunkName: \"icon-assets-Chevron\" */\"@svgr/webpack?-svgo!../../icons/Chevron.svg\");\r\nexport const CircleClose = () => import(/* webpackChunkName: \"icon-assets-CircleClose\" */\"@svgr/webpack?-svgo!../../icons/CircleClose.svg\");\r\nexport const ClearNight = () => import(/* webpackChunkName: \"icon-assets-ClearNight\" */\"@svgr/webpack?-svgo!../../icons/ClearNight.svg\");\r\nexport const ClearNightWhite = () => import(/* webpackChunkName: \"icon-assets-ClearNightWhite\" */\"@svgr/webpack?-svgo!../../icons/ClearNightWhite.svg\");\r\nexport const Close = () => import(/* webpackChunkName: \"icon-assets-Close\" */\"@svgr/webpack?-svgo!../../icons/Close.svg\");\r\nexport const Cloudy = () => import(/* webpackChunkName: \"icon-assets-Cloudy\" */\"@svgr/webpack?-svgo!../../icons/Cloudy.svg\");\r\nexport const CloudyWhite = () => import(/* webpackChunkName: \"icon-assets-CloudyWhite\" */\"@svgr/webpack?-svgo!../../icons/CloudyWhite.svg\");\r\nexport const Copy = () => import(/* webpackChunkName: \"icon-assets-Copy\" */\"@svgr/webpack?-svgo!../../icons/Copy.svg\");\r\nexport const DarkModeHotel = () => import(/* webpackChunkName: \"icon-assets-DarkModeHotel\" */\"@svgr/webpack?-svgo!../../icons/DarkModeHotel.svg\");\r\nexport const DayTime = () => import(/* webpackChunkName: \"icon-assets-DayTime\" */\"@svgr/webpack?-svgo!../../icons/DayTime.svg\");\r\nexport const Delete = () => import(/* webpackChunkName: \"icon-assets-Delete\" */\"@svgr/webpack?-svgo!../../icons/Delete.svg\");\r\nexport const Dislike = () => import(/* webpackChunkName: \"icon-assets-Dislike\" */\"@svgr/webpack?-svgo!../../icons/Dislike.svg\");\r\nexport const DislikeText = () => import(/* webpackChunkName: \"icon-assets-DislikeText\" */\"@svgr/webpack?-svgo!../../icons/DislikeText.svg\");\r\nexport const Disliked = () => import(/* webpackChunkName: \"icon-assets-Disliked\" */\"@svgr/webpack?-svgo!../../icons/Disliked.svg\");\r\nexport const DislikedText = () => import(/* webpackChunkName: \"icon-assets-DislikedText\" */\"@svgr/webpack?-svgo!../../icons/DislikedText.svg\");\r\nexport const DislikedLight = () => import(/* webpackChunkName: \"icon-assets-DislikedLight\" */\"@svgr/webpack?-svgo!../../icons/DislikedLight.svg\");\r\nexport const Docx = () => import(/* webpackChunkName: \"icon-assets-Docx\" */\"@svgr/webpack?-svgo!../../icons/Docx.svg\");\r\nexport const DoubleTap = () => import(/* webpackChunkName: \"icon-assets-DoubleTap\" */\"@svgr/webpack?-svgo!../../icons/DoubleTap.svg\");\r\nexport const Download = () => import(/* webpackChunkName: \"icon-assets-Download\" */\"@svgr/webpack?-svgo!../../icons/Download.svg\");\r\nexport const Edit = () => import(/* webpackChunkName: \"icon-assets-Edit\" */\"@svgr/webpack?-svgo!../../icons/Edit.svg\");\r\nexport const Edited = () => import(/* webpackChunkName: \"icon-assets-Edited\" */\"@svgr/webpack?-svgo!../../icons/Edited.svg\");\r\nexport const Ellipses = () => import(/* webpackChunkName: \"icon-assets-Ellipses\" */\"@svgr/webpack?-svgo!../../icons/Ellipses.svg\");\r\nexport const EllipsesLight = () => import(/* webpackChunkName: \"icon-assets-EllipsesLight\" */\"@svgr/webpack?-svgo!../../icons/EllipsesLight.svg\");\r\nexport const EmptyMruDark = () => import(/* webpackChunkName: \"icon-assets-EmptyMruDark\" */\"@svgr/webpack?-svgo!../../icons/EmptyMruDark.svg\");\r\nexport const EmptyMruLight = () => import(/* webpackChunkName: \"icon-assets-EmptyMruLight\" */\"@svgr/webpack?-svgo!../../icons/EmptyMruLight.svg\");\r\nexport const EmptyPinnedDark = () => import(/* webpackChunkName: \"icon-assets-EmptyPinnedDark\" */\"@svgr/webpack?-svgo!../../icons/EmptyPinnedDark.svg\");\r\nexport const EmptyPinnedLight = () => import(/* webpackChunkName: \"icon-assets-EmptyPinnedLight\" */\"@svgr/webpack?-svgo!../../icons/EmptyPinnedLight.svg\");\r\nexport const EmptySharedDark = () => import(/* webpackChunkName: \"icon-assets-EmptySharedDark\" */\"@svgr/webpack?-svgo!../../icons/EmptySharedDark.svg\");\r\nexport const EmptySharedLight = () => import(/* webpackChunkName: \"icon-assets-EmptySharedLight\" */\"@svgr/webpack?-svgo!../../icons/EmptySharedLight.svg\");\r\nexport const Excel = () => import(/* webpackChunkName: \"icon-assets-Excel\" */\"@svgr/webpack?-svgo!../../icons/Excel.svg\");\r\nexport const Facebook = () => import(/* webpackChunkName: \"icon-assets-Facebook\" */\"@svgr/webpack?-svgo!../../icons/Facebook.svg\");\r\nexport const FacebookText = () => import(/* webpackChunkName: \"icon-assets-FacebookText\" */\"@svgr/webpack?-svgo!../../icons/FacebookText.svg\");\r\nexport const FacebookTextBlack = () => import(/* webpackChunkName: \"icon-assets-FacebookTextBlack\" */\"@svgr/webpack?-svgo!../../icons/FacebookTextBlack.svg\");\r\nexport const Fog = () => import(/* webpackChunkName: \"icon-assets-Fog\" */\"@svgr/webpack?-svgo!../../icons/Fog.svg\");\r\nexport const FogWhite = () => import(/* webpackChunkName: \"icon-assets-FogWhite\" */\"@svgr/webpack?-svgo!../../icons/FogWhite.svg\");\r\nexport const Form = () => import(/* webpackChunkName: \"icon-assets-Form\" */\"@svgr/webpack?-svgo!../../icons/Form.svg\");\r\nexport const Folder = () => import(/* webpackChunkName: \"icon-assets-Folder\" */\"@svgr/webpack?-svgo!../../icons/Folder.svg\");\r\nexport const FolderOpen = () => import(/* webpackChunkName: \"icon-assets-FolderOpen\" */\"@svgr/webpack?-svgo!../../icons/FolderOpen.svg\");\r\nexport const FreezingRain = () => import(/* webpackChunkName: \"icon-assets-FreezingRain\" */\"@svgr/webpack?-svgo!../../icons/FreezingRain.svg\");\r\nexport const FreezingRainWhite = () => import(/* webpackChunkName: \"icon-assets-FreezingRainWhite\" */\"@svgr/webpack?-svgo!../../icons/FreezingRainWhite.svg\");\r\nexport const GalleryFullscreen = () => import(/* webpackChunkName: \"icon-assets-GalleryFullscreen\" */\"@svgr/webpack?-svgo!../../icons/GalleryFullscreen.svg\");\r\nexport const GalleryMediaIcon = () => import(/* webpackChunkName: \"icon-assets-GalleryMediaIcon\" */\"@svgr/webpack?-svgo!../../icons/GalleryMediaIcon.svg\");\r\nexport const GenericFile = () => import(/* webpackChunkName: \"icon-assets-GenericFile\" */\"@svgr/webpack?-svgo!../../icons/GenericFile.svg\");\r\nexport const GridView = () => import(/* webpackChunkName: \"icon-assets-GridView\" */\"@svgr/webpack?-svgo!../../icons/GridView.svg\");\r\nexport const HailDay = () => import(/* webpackChunkName: \"icon-assets-HailDay\" */\"@svgr/webpack?-svgo!../../icons/HailDay.svg\");\r\nexport const HailDayWhite = () => import(/* webpackChunkName: \"icon-assets-HailDayWhite\" */\"@svgr/webpack?-svgo!../../icons/HailDayWhite.svg\");\r\nexport const HailNight = () => import(/* webpackChunkName: \"icon-assets-HailNight\" */\"@svgr/webpack?-svgo!../../icons/HailNight.svg\");\r\nexport const HailNightWhite = () => import(/* webpackChunkName: \"icon-assets-HailNightWhite\" */\"@svgr/webpack?-svgo!../../icons/HailNightWhite.svg\");\r\nexport const HazeSmoke = () => import(/* webpackChunkName: \"icon-assets-HazeSmoke\" */\"@svgr/webpack?-svgo!../../icons/HazeSmoke.svg\");\r\nexport const HazeSmokeWhite = () => import(/* webpackChunkName: \"icon-assets-HazeSmokeWhite\" */\"@svgr/webpack?-svgo!../../icons/HazeSmokeWhite.svg\");\r\nexport const HeavySnow = () => import(/* webpackChunkName: \"icon-assets-HeavySnow\" */\"@svgr/webpack?-svgo!../../icons/HeavySnow.svg\");\r\nexport const HeavySnowWhite = () => import(/* webpackChunkName: \"icon-assets-HeavySnowWhite\" */\"@svgr/webpack?-svgo!../../icons/HeavySnowWhite.svg\");\r\nexport const Hide = () => import(/* webpackChunkName: \"icon-assets-Hide\" */\"@svgr/webpack?-svgo!../../icons/Hide.svg\");\r\nexport const HideStory = () => import(/* webpackChunkName: \"icon-assets-HideStory\" */\"@svgr/webpack?-svgo!../../icons/HideStory.svg\");\r\nexport const Hotel = () => import(/* webpackChunkName: \"icon-assets-Hotel\" */\"@svgr/webpack?-svgo!../../icons/Hotel.svg\");\r\nexport const Information = () => import(/* webpackChunkName: \"icon-assets-Information\" */\"@svgr/webpack?-svgo!../../icons/Information.svg\")\r\nexport const InteractionRequiredDark = () => import(/* webpackChunkName: \"icon-assets-InteractionRequiredDark\" */\"@svgr/webpack?-svgo!../../icons/InteractionRequiredDark.svg\");\r\nexport const InteractionRequiredLight = () => import(/* webpackChunkName: \"icon-assets-InteractionRequiredLight\" */\"@svgr/webpack?-svgo!../../icons/InteractionRequiredLight.svg\");;\r\nexport const Interested = () => import(/* webpackChunkName: \"icon-assets-Interested\" */\"@svgr/webpack?-svgo!../../icons/Interested.svg\");\r\nexport const LightRain = () => import(/* webpackChunkName: \"icon-assets-LightRain\" */\"@svgr/webpack?-svgo!../../icons/LightRain.svg\");\r\nexport const LightRainWhite = () => import(/* webpackChunkName: \"icon-assets-LightRainWhite\" */\"@svgr/webpack?-svgo!../../icons/LightRainWhite.svg\");\r\nexport const LightSnow = () => import(/* webpackChunkName: \"icon-assets-LightSnow\" */\"@svgr/webpack?-svgo!../../icons/LightSnow.svg\");\r\nexport const LightSnowWhite = () => import(/* webpackChunkName: \"icon-assets-LightSnowWhite\" */\"@svgr/webpack?-svgo!../../icons/LightSnowWhite.svg\");\r\nexport const Like = () => import(/* webpackChunkName: \"icon-assets-Like\" */\"@svgr/webpack?-svgo!../../icons/Like.svg\");\r\nexport const LikeText = () => import(/* webpackChunkName: \"icon-assets-LikeText\" */\"@svgr/webpack?-svgo!../../icons/LikeText.svg\");\r\nexport const Liked = () => import(/* webpackChunkName: \"icon-assets-Liked\" */\"@svgr/webpack?-svgo!../../icons/Liked.svg\");\r\nexport const LikedText = () => import(/* webpackChunkName: \"icon-assets-LikedText\" */\"@svgr/webpack?-svgo!../../icons/LikedText.svg\");\r\nexport const Line = () => import(/* webpackChunkName: \"icon-assets-Line\" */\"@svgr/webpack?-svgo!../../icons/Line.svg\");\r\nexport const LinkedIn = () => import(/* webpackChunkName: \"icon-assets-LinkedIn\" */\"@svgr/webpack?-svgo!../../icons/LinkedIn.svg\");\r\nexport const LinkedInBlack = () => import(/* webpackChunkName: \"icon-assets-LinkedInBlack\" */\"@svgr/webpack?-svgo!../../icons/LinkedInBlack.svg\");\r\nexport const LinkedInText = () => import(/* webpackChunkName: \"icon-assets-LinkedInText\" */\"@svgr/webpack?-svgo!../../icons/LinkedInText.svg\");\r\nexport const Mail = () => import(/* webpackChunkName: \"icon-assets-Mail\" */\"@svgr/webpack?-svgo!../../icons/Mail.svg\");\r\nexport const MailBlack = () => import(/* webpackChunkName: \"icon-assets-MailBlack\" */\"@svgr/webpack?-svgo!../../icons/MailBlack.svg\");\r\nexport const ManagedBriefcase = () => import(/* webpackChunkName: \"icon-assets-ManagedBriefcase\" */\"@svgr/webpack?-svgo!../../icons/ManagedBriefcase.svg\");\r\nexport const Message = () => import(/* webpackChunkName: \"icon-assets-Message\" */\"@svgr/webpack?-svgo!../../icons/Message.svg\");\r\nexport const Messages = () => import(/* webpackChunkName: \"icon-assets-Messages\" */\"@svgr/webpack?-svgo!../../icons/Messages.svg\");\r\nexport const MicrosoftNews = () => import(/* webpackChunkName: \"icon-assets-MicrosoftNews\" */\"@svgr/webpack?-svgo!../../icons/MicrosoftNews.svg\");\r\nexport const MicrosoftNewsFull = () => import(/* webpackChunkName: \"icon-assets-MicrosoftNews\" */\"@svgr/webpack?-svgo!../../icons/MicrosoftNewsFull.svg\");\r\nexport const MicrosoftNewsFull_FR = () => import(/* webpackChunkName: \"icon-assets-MicrosoftNews_FR\" */\"@svgr/webpack?-svgo!../../icons/MicrosoftNewsFull_FR.svg\");\r\nexport const MicrosoftNewsFull_ZH = () => import(/* webpackChunkName: \"icon-assets-MicrosoftNews_ZH\" */\"@svgr/webpack?-svgo!../../icons/MicrosoftNewsFull_ZH.svg\");\r\nexport const ModerateRain = () => import(/* webpackChunkName: \"icon-assets-ModerateRain\" */\"@svgr/webpack?-svgo!../../icons/ModerateRain.svg\");\r\nexport const ModerateRainWhite = () => import(/* webpackChunkName: \"icon-assets-ModerateRainWhite\" */\"@svgr/webpack?-svgo!../../icons/ModerateRainWhite.svg\");\r\nexport const Movie = () => import(/* webpackChunkName: \"icon-assets-Movie\" */\"@svgr/webpack?-svgo!../../icons/Movie.svg\");\r\nexport const NightTime = () => import(/* webpackChunkName: \"icon-assets-NightTime\" */\"@svgr/webpack?-svgo!../../icons/NightTime.svg\");\r\nexport const NotificationFivePlusSign = () => import(/* webpackChunkName: \"icon-assets-Notification-Five-Plus-Sign\" */\"@svgr/webpack?-svgo!../../icons/NotificationFivePlusSign.svg\");\r\nexport const NotificationRefreshArrow = () => import(/* webpackChunkName: \"icon-assets-Notification-Five-Plus-Sign\" */\"@svgr/webpack?-svgo!../../icons/NotificationRefreshArrow.svg\");\r\nexport const OneDrive = () => import(/* webpackChunkName: \"icon-assets-OneDrive\" */\"@svgr/webpack?-svgo!../../icons/OneDrive.svg\");\r\nexport const OfficeFormsLogo = () => import(/* webpackChunkName: \"icon-assets-OfficeFormsLogo\" */\"@svgr/webpack?-svgo!../../icons/OfficeFormsLogo.svg\");\r\nexport const OneNote = () => import(/* webpackChunkName: \"icon-assets-OneNote\" */\"@svgr/webpack?-svgo!../../icons/OneNote.svg\");\r\nexport const Onetoc = () => import(/* webpackChunkName: \"icon-assets-Onetoc\" */\"@svgr/webpack?-svgo!../../icons/Onetoc.svg\");\r\nexport const Outlook = () => import(/* webpackChunkName: \"icon-assets-Outlook\" */\"@svgr/webpack?-svgo!../../icons/Outlook.svg\");\r\nexport const PartlyCloudyDay = () => import(/* webpackChunkName: \"icon-assets-PartlyCloudyDay\" */\"@svgr/webpack?-svgo!../../icons/PartlyCloudyDay.svg\");\r\nexport const PartlyCloudyDayWhite = () => import(/* webpackChunkName: \"icon-assets-PartlyCloudyDayWhite\" */\"@svgr/webpack?-svgo!../../icons/PartlyCloudyDayWhite.svg\");\r\nexport const PartlyCloudyNight = () => import(/* webpackChunkName: \"icon-assets-PartlyCloudyNight\" */\"@svgr/webpack?-svgo!../../icons/PartlyCloudyNight.svg\");\r\nexport const PartlyCloudyNightWhite = () => import(/* webpackChunkName: \"icon-assets-PartlyCloudyNightWhite\" */\"@svgr/webpack?-svgo!../../icons/PartlyCloudyNightWhite.svg\");\r\nexport const Pdf = () => import(/* webpackChunkName: \"icon-assets-Pdf\" */\"@svgr/webpack?-svgo!../../icons/Pdf.svg\");\r\nexport const People = () => import(/* webpackChunkName: \"icon-assets-People\" */\"@svgr/webpack?-svgo!../../icons/People.svg\");\r\nexport const Pin = () => import(/* webpackChunkName: \"icon-assets-Pin\" */\"@svgr/webpack?-svgo!../../icons/Pin.svg\");\r\nexport const PowerPoint = () => import(/* webpackChunkName: \"icon-assets-PowerPoint\" */\"@svgr/webpack?-svgo!../../icons/PowerPoint.svg\");\r\nexport const Pptx = () => import(/* webpackChunkName: \"icon-assets-Pptx\" */\"@svgr/webpack?-svgo!../../icons/Pptx.svg\");\r\nexport const RainShowersDay = () => import(/* webpackChunkName: \"icon-assets-RainShowersDay\" */\"@svgr/webpack?-svgo!../../icons/RainShowersDay.svg\");\r\nexport const RainShowersDayWhite = () => import(/* webpackChunkName: \"icon-assets-RainShowersDayWhite\" */\"@svgr/webpack?-svgo!../../icons/RainShowersDayWhite.svg\");\r\nexport const RainShowersNight = () => import(/* webpackChunkName: \"icon-assets-RainShowersNight\" */\"@svgr/webpack?-svgo!../../icons/RainShowersNight.svg\");\r\nexport const RainShowersNightWhite = () => import(/* webpackChunkName: \"icon-assets-RainShowersNightWhite\" */\"@svgr/webpack?-svgo!../../icons/RainShowersNightWhite.svg\");\r\nexport const RainSnow = () => import(/* webpackChunkName: \"icon-assets-RainSnow\" */\"@svgr/webpack?-svgo!../../icons/RainSnow.svg\");\r\nexport const RainSnowWhite = () => import(/* webpackChunkName: \"icon-assets-RainSnowWhite\" */\"@svgr/webpack?-svgo!../../icons/RainSnowWhite.svg\");\r\nexport const RainSnowShowersDay = () => import(/* webpackChunkName: \"icon-assets-RainSnowShowersDay\" */\"@svgr/webpack?-svgo!../../icons/RainSnowShowersDay.svg\");\r\nexport const RainSnowShowersDayWhite = () => import(/* webpackChunkName: \"icon-assets-RainSnowShowersDayWhite\" */\"@svgr/webpack?-svgo!../../icons/RainSnowShowersDayWhite.svg\");\r\nexport const RainSnowShowersNight = () => import(/* webpackChunkName: \"icon-assets-RainSnowShowersNight\" */\"@svgr/webpack?-svgo!../../icons/RainSnowShowersNight.svg\");\r\nexport const RainSnowShowersNightWhite = () => import(/* webpackChunkName: \"icon-assets-RainSnowShowersNightWhite\" */\"@svgr/webpack?-svgo!../../icons/RainSnowShowersNightWhite.svg\");\r\nexport const Refresh = () => import(/* webpackChunkName: \"icon-assets-Refresh\" */\"@svgr/webpack?-svgo!../../icons/Refresh.svg\");\r\nexport const Remove = () => import(/* webpackChunkName: \"icon-assets-Remove\" */\"@svgr/webpack?-svgo!../../icons/Remove.svg\");\r\nexport const VideoMediaIcon = () => import(/* webpackChunkName: \"icon-assets-VideoMediaIcon\" */\"@svgr/webpack?-svgo!../../icons/VideoMediaIcon.svg\");\r\nexport const VideoPlay = () => import(/* webpackChunkName: \"icon-assets-VideoPlay\" */\"@svgr/webpack?-svgo!../../icons/VideoPlay.svg\");\r\nexport const Save = () => import(/* webpackChunkName: \"icon-assets-Save\" */\"@svgr/webpack?-svgo!../../icons/Save.svg\");\r\nexport const Saved = () => import(/* webpackChunkName: \"icon-assets-Saved\" */\"@svgr/webpack?-svgo!../../icons/Saved.svg\");\r\nexport const Search = () => import(/* webpackChunkName: \"icon-assets-Search\" */\"@svgr/webpack?-svgo!../../icons/Search.svg\");\r\nexport const Share = () => import(/* webpackChunkName: \"icon-assets-Share\" */\"@svgr/webpack?-svgo!../../icons/Share.svg\");\r\nexport const ShareLight = () => import(/* webpackChunkName: \"icon-assets-ShareLight\" */\"@svgr/webpack?-svgo!../../icons/ShareLight.svg\");\r\nexport const Sharepoint = () => import(/* webpackChunkName: \"icon-assets-Sharepoint\" */\"@svgr/webpack?-svgo!../../icons/Sharepoint.svg\");\r\nexport const Skype = () => import(/* webpackChunkName: \"icon-assets-Skype\" */\"@svgr/webpack?-svgo!../../icons/Skype.svg\");\r\nexport const SkypeOffice = () => import(/* webpackChunkName: \"icon-assets-SkypeOffice\" */\"@svgr/webpack?-svgo!../../icons/SkypeOffice.svg\");\r\nexport const SnowShowersDay = () => import(/* webpackChunkName: \"icon-assets-SnowShowersDay\" */\"@svgr/webpack?-svgo!../../icons/SnowShowersDay.svg\");\r\nexport const SnowShowersDayWhite = () => import(/* webpackChunkName: \"icon-assets-SnowShowersDayWhite\" */\"@svgr/webpack?-svgo!../../icons/SnowShowersDayWhite.svg\");\r\nexport const SnowShowersNight = () => import(/* webpackChunkName: \"icon-assets-SnowShowersNight\" */\"@svgr/webpack?-svgo!../../icons/SnowShowersNight.svg\");\r\nexport const SnowShowersNightWhite = () => import(/* webpackChunkName: \"icon-assets-SnowShowersNightWhite\" */\"@svgr/webpack?-svgo!../../icons/SnowShowersNightWhite.svg\");\r\nexport const SunnyDay = () => import(/* webpackChunkName: \"icon-assets-SunnyDay\" */\"@svgr/webpack?-svgo!../../icons/SunnyDay.svg\");\r\nexport const SunnyDayWhite = () => import(/* webpackChunkName: \"icon-assets-SunnyDayWhite\" */\"@svgr/webpack?-svgo!../../icons/SunnyDayWhite.svg\");\r\nexport const Sway = () => import(/* webpackChunkName: \"icon-assets-Sway\" */\"@svgr/webpack?-svgo!../../icons/Sway.svg\");\r\nexport const SwayApp = () => import(/* webpackChunkName: \"icon-assets-SwayApp\" */\"@svgr/webpack?-svgo!../../icons/SwayApp.svg\");\r\nexport const Teams = () => import(/* webpackChunkName: \"icon-assets-Teams\" */\"@svgr/webpack?-svgo!../../icons/Teams.svg\");\r\nexport const ThumbnailView = () => import(/* webpackChunkName: \"icon-assets-ThumbnailView\" */\"@svgr/webpack?-svgo!../../icons/ThumbnailView.svg\");\r\nexport const Thunderstorms = () => import(/* webpackChunkName: \"icon-assets-Thunderstorms\" */\"@svgr/webpack?-svgo!../../icons/Thunderstorms.svg\");\r\nexport const ThunderstormsWhite = () => import(/* webpackChunkName: \"icon-assets-ThunderstormsWhite\" */\"@svgr/webpack?-svgo!../../icons/ThunderstormsWhite.svg\");\r\nexport const Trending = () => import(/* webpackChunkName: \"icon-assets-Trending\" */\"@svgr/webpack?-svgo!../../icons/Trending.svg\");\r\nexport const Twitter = () => import(/* webpackChunkName: \"icon-assets-Twitter\" */\"@svgr/webpack?-svgo!../../icons/Twitter.svg\");\r\nexport const TwitterBlack = () => import(/* webpackChunkName: \"icon-assets-TwitterBlack\" */\"@svgr/webpack?-svgo!../../icons/TwitterBlack.svg\");\r\nexport const TwitterText = () => import(/* webpackChunkName: \"icon-assets-TwitterText\" */\"@svgr/webpack?-svgo!../../icons/TwitterText.svg\");\r\nexport const Unpin = () => import(/* webpackChunkName: \"icon-assets-Unpin\" */\"@svgr/webpack?-svgo!../../icons/Unpin.svg\");\r\nexport const VerticalSeparator = () => import(/* webpackChunkName: \"icon-assets-VerticalSeparator\" */\"@svgr/webpack?-svgo!../../icons/VerticalSeparator.svg\");\r\nexport const Visio = () => import(/* webpackChunkName: \"icon-assets-Visio\" */\"@svgr/webpack?-svgo!../../icons/Visio.svg\");\r\nexport const Vsdx = () => import(/* webpackChunkName: \"icon-assets-Vsdx\" */\"@svgr/webpack?-svgo!../../icons/Vsdx.svg\");\r\nexport const WeatherAlert = () => import(/* webpackChunkName: \"icon-assets-WeatherAlert\" */\"@svgr/webpack?-svgo!../../icons/WeatherAlert.svg\");\r\nexport const WhatsApp = () => import(/* webpackChunkName: \"icon-assets-WhatsApp\" */\"@svgr/webpack?-svgo!../../icons/WhatsApp.svg\");\r\nexport const WhatsAppBlack = () => import(/* webpackChunkName: \"icon-assets-WhatsAppBlack\" */\"@svgr/webpack?-svgo!../../icons/WhatsAppBlack.svg\");\r\nexport const Windy = () => import(/* webpackChunkName: \"icon-assets-Windy\" */\"@svgr/webpack?-svgo!../../icons/Windy.svg\");\r\nexport const WindyWhite = () => import(/* webpackChunkName: \"icon-assets-WindyWhite\" */\"@svgr/webpack?-svgo!../../icons/WindyWhite.svg\");\r\nexport const Word = () => import(/* webpackChunkName: \"icon-assets-Word\" */\"@svgr/webpack?-svgo!../../icons/Word.svg\");\r\nexport const World = () => import(/* webpackChunkName: \"icon-assets-World\" */\"@svgr/webpack?-svgo!../../icons/World.svg\");\r\nexport const Xlsx = () => import(/* webpackChunkName: \"icon-assets-Xlsx\" */\"@svgr/webpack?-svgo!../../icons/Xlsx.svg\");\r\nexport const Yammer = () => import(/* webpackChunkName: \"icon-assets-Yammer\" */\"@svgr/webpack?-svgo!../../icons/Yammer.svg\");\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ManagedClasses } from \"@microsoft/fast-jss-manager\";\r\n\r\nimport { IconCssClasses } from \"./Icon.styles\";\r\nimport * as Glyph from \"./icons\";\r\nimport * as GlyphInline from \"./icons/GlyphInline\";\r\n\r\nexport interface IconManagedClasses extends ManagedClasses { }\r\n\r\nexport type GlyphType = (() => Promise) | string;\r\n\r\nexport { Glyph, GlyphInline };\r\n\r\n/**\r\n * Property contract for the {CardAction} component\r\n */\r\nexport interface IconHandledProps extends IconManagedClasses {\r\n /** Icon type props */\r\n glyphType: GlyphType,\r\n /** Aria label optional type props */\r\n ariaLabel?: string,\r\n width?: string,\r\n height?: string,\r\n fill?: string,\r\n onError?: (error: Error) => void,\r\n wrapperClassName?: string\r\n}\r\n\r\nexport interface IconUnhandledProps extends React.HTMLAttributes {\r\n}\r\n\r\nexport type IconProps = IconHandledProps & IconUnhandledProps;","// © Microsoft Corporation. All rights reserved.\r\n\r\n// TODO: This should be considered for moving it to the Interests experience wrapper, once that\r\n// code arrives, since this is specific to that experience\r\n\r\n/**\r\n * Subnav TabId Enum object\r\n * @export\r\n * @type {enum}\r\n */\r\nexport enum SubnavTabId {\r\n None = 0,\r\n MyFeed = 1,\r\n XFeed = 2,\r\n Interests = 3\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { IconHandledProps as BaseHandledProps, IconProps as BaseIconProps, IconManagedClasses, IconUnhandledProps } from \"./Icon.props\";\r\nimport { Glyph, GlyphInline, GlyphType } from \"./Icon.props\";\r\nimport manageJss, { ManagedJSSProps } from \"@microsoft/fast-jss-manager-react\";\r\n\r\nimport { Icon as BaseIcon } from \"./Icon\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { IconCssClasses as IconClassNameContract } from \"./Icon.styles\";\r\nimport { IconStyles } from \"./Icon.styles\";\r\nimport { Subtract } from \"utility-types\";\r\n\r\nconst Icon = manageJss(IconStyles)(BaseIcon);\r\ntype Icon = InstanceType;\r\ninterface IconHandledProps extends Subtract { }\r\ntype IconProps = ManagedJSSProps;\r\n\r\nexport {\r\n Icon,\r\n IconProps,\r\n IconClassNameContract,\r\n IconHandledProps,\r\n IconUnhandledProps,\r\n GlyphType,\r\n Glyph,\r\n GlyphInline\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ComponentStyles } from \"@microsoft/fast-jss-manager\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\n\r\n/** CSS class names to apply to various {CardAction} components */\r\nexport interface IconCssClasses {\r\n /** CSS class for the image icon */\r\n icon?: string,\r\n /** CSS class for the inline icon */\r\n icon_inline?: string\r\n}\r\n\r\n/**\r\n * The main JSS stylesheet for {CardAction}\r\n */\r\nexport const IconStyles: ComponentStyles = {\r\n icon: {\r\n \"max-height\": \"100%\",\r\n \"max-width\": \"100%\"\r\n },\r\n icon_inline: {\r\n \"&&\": {\r\n width: \"auto\",\r\n height: \"auto\"\r\n }\r\n }\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { IconHandledProps, IconProps, IconUnhandledProps } from \"./Icon.props\";\r\n\r\nimport Foundation from \"@microsoft/fast-components-foundation-react\";\r\nimport { Glyph } from \".\";\r\nimport { HandledPropsKeys } from \"@msnews/core\";\r\nimport React from \"react\";\r\n\r\n/**\r\n * Icon component\r\n * @class - Icon\r\n * @classdesc - The Icon component. Renders the image with respective glyph icon\r\n * @default\r\n */\r\nexport class Icon extends Foundation {\r\n /**\r\n * Component HandledProps enumeration. Anything not enumerated here will be included in the experience root HTML tag via unhandledProps()\r\n */\r\n protected handledProps: HandledPropsKeys = {\r\n ariaLabel: undefined,\r\n fill: undefined,\r\n glyphType: undefined,\r\n height: undefined,\r\n managedClasses: undefined,\r\n onError: undefined,\r\n width: undefined,\r\n wrapperClassName: undefined\r\n };\r\n\r\n constructor(props: IconProps) {\r\n super(props);\r\n }\r\n\r\n /**\r\n * Component renderer\r\n * @public\r\n * @method\r\n * @returns {JSX.Element} the image component containing a glyph icon\r\n */\r\n public render(): JSX.Element {\r\n const { ariaLabel, fill, height, managedClasses, width, glyphType, wrapperClassName } = this.props;\r\n if (!glyphType) {\r\n return (null);\r\n }\r\n const role = ariaLabel ? \"img\" : \"presentation\";\r\n\r\n if (typeof glyphType === \"string\") {\r\n // when glyphType is string, use img tag\r\n let icon = glyphType as string;\r\n if (Glyph[icon]) {\r\n icon = Glyph[icon];\r\n }\r\n return ();\r\n }\r\n\r\n const IconComponent = React.lazy(() => glyphType()\r\n .then(module => ({default: module.ReactComponent}))\r\n .catch(this.fallBackInlineComponent));\r\n\r\n const attrProps: React.SVGAttributes = {};\r\n if (width) {\r\n attrProps.width = width;\r\n }\r\n if (height) {\r\n attrProps.height = height;\r\n }\r\n\r\n return (\r\n \r\n } >\r\n \r\n \r\n \r\n );\r\n }\r\n\r\n /**\r\n * fallback element when inline fetch fails.\r\n */\r\n private fallBackInlineComponent = () => ({default: () => });\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { AppError, WebWorkerErrors, logger, tryGetPerfTimeline } from \"@msnews/diagnostics\";\r\n\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\n\r\ndeclare global {\r\n /** Adding webWorker to Window */\r\n interface Window {\r\n /** Global flag indicating if web worker is present */\r\n _isWebWorkerPresent: boolean;\r\n\r\n /** Web worker instance */\r\n webWorker?: Worker;\r\n\r\n /** Web worker runtime errors */\r\n webWorkerErrors?: any[];\r\n }\r\n}\r\n\r\n/** Web worker request interface. */\r\nexport interface WebWorkerRequest {\r\n /** The message id. */\r\n id: string;\r\n\r\n /** The type of message. */\r\n type?: string;\r\n\r\n /** The additional message payload */\r\n payload?: any;\r\n}\r\n\r\n/** Web worker response interface. */\r\nexport interface WebWorkerResponse {\r\n /** The message id. */\r\n id: string;\r\n\r\n /** The item fetched status. */\r\n fetched: boolean;\r\n\r\n /** The item payload. */\r\n payload: any;\r\n}\r\n\r\n/**\r\n * Reports web worker presence.\r\n *\r\n * **NOTE**: Make sure to update the **_window._isWebWorkerPresent_** flag as well\r\n * while updating this, since the diagnostics lib doesn't have access to the core lib.\r\n */\r\nexport let isWebWorkerPresent: boolean;\r\n\r\n/** Web-worker message-map entry */\r\nexport interface WebWorkerMessageMapEntry {\r\n /** The message type (default is \"data\") */\r\n type: string;\r\n\r\n /** The callback, if any, that receives the data payload for the message */\r\n callback: (data: any) => void;\r\n}\r\n\r\n/** The message map from message id to the WebWorkerMessageMapEntry */\r\nconst messages = new Map();\r\n\r\nlet logAppError: (data: AppError) => void;\r\n\r\n/** The perf timeline for the web-worker interface */\r\nconst perfTimeline = tryGetPerfTimeline(\"WebWorkerUtility\", \"WebWorkerUtility\", true);\r\n\r\n/**\r\n * Initialize isWebWorkerPresent. And this function also serve as test hook.\r\n * @param override - The test override\r\n */\r\nexport function init(override?: boolean): void {\r\n isWebWorkerPresent = false;\r\n if (canUseDOM()) {\r\n isWebWorkerPresent = (typeof override !== \"undefined\" ? override : !!window.webWorker);\r\n window._isWebWorkerPresent = isWebWorkerPresent;\r\n }\r\n\r\n if (!isWebWorkerPresent) {\r\n return;\r\n }\r\n\r\n window.webWorker.onmessage = (event: MessageEvent) => {\r\n const { data: response } = event;\r\n const pendingMessage = messages.get(response.id);\r\n\r\n if (!pendingMessage) {\r\n return;\r\n }\r\n\r\n if (pendingMessage.type === \"data\") {\r\n messages.delete(response.id);\r\n }\r\n\r\n const callback = pendingMessage.callback;\r\n if (callback) {\r\n callback(response);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * This function utility is converting web worker's postMessage communication into an async function.\r\n * It's sends given request to web worker, returns a promise, and promise is resolved when response is received from web worker.\r\n * @param request - The message to send\r\n * @param timeoutInMs(optional) - Timeout in milliseconds after which the promise will resolve with the default(failed) web worker response\r\n * @returns A promise to return WebWorkerResponse\r\n */\r\nexport function getFromWebWorker(request: WebWorkerRequest, timeoutInMs?: number): Promise {\r\n const defaultResponse = {\r\n id: (request && request.id) || \"\",\r\n fetched: false,\r\n payload: null\r\n };\r\n\r\n if (!isWebWorkerPresent || !request || !request.id) {\r\n return Promise.resolve(defaultResponse);\r\n }\r\n\r\n let endGetFromWebWorker = perfTimeline && perfTimeline.startMeasure(request.id).endMeasure;\r\n\r\n let promiseTimeout;\r\n let timeOutPromise;\r\n\r\n // If timeout is provided, create a promise that will resolve after the timeout expires\r\n if (timeoutInMs) {\r\n timeOutPromise = new Promise(resolve => {\r\n promiseTimeout = setTimeout(\r\n () => {\r\n // Request timed out, we need not process the response if it's returned later, remove from messages map\r\n messages.delete(request.id);\r\n\r\n const errorMessage = `Web worker request timed out after ${timeoutInMs}ms for request id: [${request.id}]`;\r\n\r\n if (logAppError) {\r\n logAppError({\r\n ...WebWorkerErrors.MessageTimeout,\r\n message: `Web worker request timed out`,\r\n pb: {\r\n ...WebWorkerErrors.MessageTimeout.pb,\r\n customMessage: errorMessage\r\n }\r\n });\r\n } else {\r\n logger.logError(errorMessage);\r\n }\r\n\r\n if (endGetFromWebWorker) {\r\n endGetFromWebWorker(\"timeout\");\r\n }\r\n\r\n resolve(defaultResponse);\r\n },\r\n timeoutInMs);\r\n });\r\n }\r\n\r\n const webWorkerPromise: Promise = new Promise(\r\n resolve => {\r\n const onMessage = (response: WebWorkerResponse) => {\r\n // We got a response from web worker, clear the promise timeout if it exists.\r\n if (promiseTimeout) {\r\n clearTimeout(promiseTimeout);\r\n }\r\n\r\n if (endGetFromWebWorker) {\r\n endGetFromWebWorker();\r\n }\r\n\r\n resolve(response);\r\n };\r\n\r\n messages.set(request.id, {\r\n type: request.type || \"data\",\r\n callback: onMessage\r\n });\r\n }\r\n );\r\n\r\n window.webWorker.postMessage({\r\n id: request.id,\r\n type: request.type || \"data\",\r\n payload: request.payload\r\n });\r\n\r\n return timeoutInMs\r\n ? Promise.race([webWorkerPromise, timeOutPromise])\r\n : webWorkerPromise;\r\n}\r\n\r\n/**\r\n * Sends given request to the web worker.\r\n * @param request - The message to send\r\n */\r\nexport function sendToWebWorker(request: WebWorkerRequest): void {\r\n if (!isWebWorkerPresent || !request || !request.id) {\r\n return;\r\n }\r\n\r\n window.webWorker.postMessage({\r\n id: request.id,\r\n type: request.type || \"command\",\r\n payload: request.payload || null\r\n });\r\n}\r\n\r\n/**\r\n * Subscribes to web worker notification\r\n * @param request subscription request\r\n * @param callback the callback to execute when notification is received\r\n */\r\nexport function subscribeWebWorkerNotification(request: WebWorkerRequest, callback: (payload: any) => void): void {\r\n if (!isWebWorkerPresent || !request || request.type !== \"subscription\" || !callback) {\r\n return;\r\n }\r\n\r\n messages.set(request.id, { type: \"subscription\", callback });\r\n window.webWorker.postMessage(request);\r\n}\r\n\r\n/**\r\n * Sets the AppError logging function and adds event listener for web worker errors.\r\n * @param handler - Error tracker function(track.trackAppErrorEvent) from @msnews/telemetry-transitional\r\n */\r\nexport function trackWebWorkerErrors(trackAppErrorEvent: (data: AppError) => void): void {\r\n if (!isWebWorkerPresent || !trackAppErrorEvent || typeof trackAppErrorEvent !== \"function\") {\r\n return;\r\n }\r\n\r\n logAppError = function(data: AppError): void {\r\n try {\r\n trackAppErrorEvent(data);\r\n } catch (ex) {\r\n logger.logError(`Failed to log web worker AppError. Error: ${JSON.stringify(ex)}`);\r\n }\r\n };\r\n\r\n // callback for unhandled runtime exceptions\r\n window.webWorker.onerror = onWebWorkerRuntimeError;\r\n\r\n // Callback for handled errors(logger.error) in web worker\r\n const onWorkerErrorMessage = (response: WebWorkerResponse) => {\r\n logAppError({\r\n ...WebWorkerErrors.HandledError,\r\n message: \"Web worker error\",\r\n pb: {\r\n ...WebWorkerErrors.HandledError.pb,\r\n customMessage: JSON.stringify(response.payload || \"\")\r\n }\r\n });\r\n };\r\n\r\n subscribeWebWorkerNotification({ id: \"WebWorkerError\", type: \"subscription\" }, onWorkerErrorMessage);\r\n\r\n // Read and log web worker errors that were reported before the main thread initialized.\r\n if (window.webWorkerErrors && Array.isArray(window.webWorkerErrors)) {\r\n window.webWorkerErrors.forEach(error => {\r\n onWebWorkerRuntimeError(error);\r\n });\r\n\r\n delete window.webWorkerErrors;\r\n }\r\n}\r\n\r\n/**\r\n * Handler for web worker error events\r\n * @param event web worker ErrorEvent\r\n */\r\nfunction onWebWorkerRuntimeError(event: ErrorEvent): void {\r\n // If ErrorEvent does not contain the filename, only possible reason could be that the web worker script 404ed.\r\n if (!event.filename) {\r\n isWebWorkerPresent = false;\r\n window._isWebWorkerPresent = isWebWorkerPresent;\r\n window.webWorker.terminate();\r\n\r\n logAppError({\r\n ...WebWorkerErrors.FileNotFound,\r\n message: \"Web worker script not found\",\r\n pb: {\r\n ...WebWorkerErrors.FileNotFound.pb,\r\n customMessage: JSON.stringify(getErrorDetails(event))\r\n }\r\n });\r\n\r\n return;\r\n }\r\n\r\n logAppError({\r\n ...WebWorkerErrors.RuntimeError,\r\n message: \"Web worker runtime error\",\r\n pb: {\r\n ...WebWorkerErrors.RuntimeError.pb,\r\n customMessage: JSON.stringify(getErrorDetails(event))\r\n }\r\n });\r\n}\r\n\r\n/** Extracts properties from error event. Direct JSON.stringify removes all properties except `isTrusted` */\r\nfunction getErrorDetails(error: ErrorEvent): any {\r\n return JSON.stringify({\r\n filename: error.filename,\r\n message: error.message,\r\n lineno: error.lineno\r\n });\r\n}\r\n\r\ninit();\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { minimumHostPagePathSegments } from \"../constants\";\r\n\r\n/**\r\n * The HostPage interface uses words defined by the Prime project for us to locate in what hostpage\r\n * the Feeds project is running.\r\n */\r\nexport interface IHostPage {\r\n originalUrl: string; // ex: https://www.msn.com/spartan/ntp/interests/my?fdhead=gizmodemo\r\n verticalKey: string, // ex: spartan or compass\r\n categoryKey: string, // ex: dhp or ntp\r\n hostName: string, // ex: www.msn.com\r\n topDomain: string, // ex: msn.com or msn.cn\r\n subcategoryKey?: string // ex: interests or discover\r\n}\r\n\r\nexport namespace HostPage {\r\n /**\r\n * This function extracts the hostPage information from the passed in href. This is based on the\r\n * Prime pathname convention of \"/vertical/category/subcategory\". If the passed href does not have at least the\r\n * category, then null is returned instead as this is considered an invalid URL.\r\n * @param {string} href - The URL, which will be used to extract the hostPage\r\n * @returns {IHostPage | null}\r\n */\r\n export function getHostPageFromUrl(href: string): IHostPage | null {\r\n const url = new URL(href);\r\n\r\n const host = url.hostname;\r\n const pathnameSegments = url.pathname.split(\"/\");\r\n\r\n // for cookie stamping that needs the msn.com or msn.cn path isntead of using the full host value\r\n const topDomainName = (host.match(/[^.]+\\.[^.\\d]+$/) || {})[0] || \"\";\r\n\r\n /**\r\n * The + 1 in the following statement is take into account the empty string \"segment\"\r\n * that would be to the left of the first backslash in a valid path like \"/spartan/ntp\"\r\n */\r\n if (pathnameSegments.length <= minimumHostPagePathSegments) {\r\n return {\r\n originalUrl: href,\r\n categoryKey: null,\r\n verticalKey: null,\r\n hostName: host,\r\n topDomain: topDomainName\r\n }; // When the user url doesn't have atleast two pathsegments the vertical and category keys are null\r\n }\r\n\r\n /**\r\n * Consider path segments that have market in it e.g.\r\n * /en-us/news/other/title/ar-cmsId\r\n * /en-us/video/animals\r\n * /en-us/sports/nfl/scores\r\n */\r\n const isMarketPresent = pathnameSegments[1].length === 5 && pathnameSegments[1].split(\"-\").length === 2;\r\n const indexOffset = isMarketPresent ? 1 : 0;\r\n\r\n let hostPage: IHostPage = {\r\n originalUrl: href,\r\n categoryKey: pathnameSegments[2 + indexOffset],\r\n verticalKey: pathnameSegments[1 + indexOffset],\r\n hostName: host,\r\n topDomain: topDomainName\r\n };\r\n\r\n if (pathnameSegments.length >= minimumHostPagePathSegments) {\r\n hostPage.subcategoryKey = pathnameSegments[3 + indexOffset];\r\n }\r\n return hostPage;\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Used to mock the LRU cache in test environments.\r\n */\r\nexport class MockLRUCache {\r\n\r\n /** cache */\r\n private cacheMap: any = {};\r\n\r\n /** Check if cache key exists */\r\n public async has(key): Promise {\r\n return !!this.cacheMap[key];\r\n }\r\n /** Get cached value by key */\r\n public async get(key): Promise {\r\n return this.cacheMap[key];\r\n }\r\n /** Set cached value by key */\r\n public async set(key, value, maxAge): Promise {\r\n this.cacheMap[key] = value;\r\n }\r\n /** Delete cached key-value pair */\r\n public async del(key): Promise {\r\n delete this.cacheMap[key];\r\n }\r\n /** Get count of total items cached */\r\n public async itemCount(): Promise {\r\n return Object.keys(this.cacheMap).length;\r\n }\r\n /** Reset entire cache */\r\n public async reset(): Promise {\r\n this.cacheMap = {};\r\n }\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Enum for different page types\r\n * @enum\r\n */\r\nexport enum PageType {\r\n Article = \"article\",\r\n ArticleFullScreen = \"articlefullscreen\",\r\n DHP = \"dhp\",\r\n Gallery = \"gallery\",\r\n GalleryFullScreen = \"galleryfullscreen\",\r\n MMX = \"mmx\",\r\n NTP = \"ntp\",\r\n Video = \"video\"\r\n}\r\n\r\n/** The AudienceMode enum */\r\nexport enum AudienceModeType {\r\n Adult = \"adult\",\r\n Enterprise = \"enterprise\",\r\n Kids = \"kids\"\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Enum for different auth cookie names\r\n * @enum\r\n */\r\nexport enum AuthCookieName {\r\n Anon = \"ANON\",\r\n AppAnon = \"APP_ANON\",\r\n Unknown = \"\"\r\n}\r\n\r\n/**\r\n * List of http-readable cookies that indicate the presence of an auth cookie\r\n */\r\nexport enum AuthCookieExistsCookieName {\r\n AnonCookieExists = \"ace\",\r\n AppAnonCookieExists = \"aace\"\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Mediator events\r\n * @export\r\n * @type {object}\r\n */\r\nexport const MediatorEventNames = {\r\n // Event fired when content actions attributes are updated (eg: new video is loaded)\r\n ContentActionsUpdated: \"contentActionsUpdated\",\r\n // Event fired when a feed is successfully followed\r\n FeedFollowed: \"feedFollowed\",\r\n // Event fired when a feed is successfully followed/un-followed to let pre-load\r\n // framework know it needs to refresh the page\r\n ForcePageReload: \"forcePageReload\",\r\n // Event fired when a feed is successfully followed/un-followed\r\n FollowedTopicsUpdated: \"followedTopicsUpdated\",\r\n // Event to fire to show a specific mediated coach mark\r\n MediatedCoachMark: \"mediated_coach_mark\",\r\n // Event fired by Prime when the tab is being changed\r\n TabNavigation: \"tab_navigation\",\r\n // Event that tells Prime feedsNav module to navigate to the specified URL\r\n TabNavigateTo: \"tab_navigate_to\",\r\n // Event fired when a topic is followed/unfollowed so SPA can re-act\r\n TopicAction: \"topic_action\",\r\n // Event fired when a 360 experience is launched\r\n Msn360: \"msn360\",\r\n // Event to fire to show card action menu\r\n CardActionInit: \"cardActionInit\",\r\n // Event to fire to post card action menu\r\n CardActionPost: \"cardActionPostEvent\",\r\n // Event to fire when interests render complete\r\n InterestsRenderComplete: \"interestsRenderCompleteEvent\",\r\n // Event to fire when an Xfeed needs to load\r\n RenderXFeed: \"show_xfeed_content\",\r\n // Event to fire when a pivot needs to load by id\r\n ShowPivotById: \"show_pivot_by_id\",\r\n // Event that tells Prime infopane module to resume the auto-rotation\r\n ResumeInfopaneAutoRotate: \"resumeInfopaneAutoRotate\"\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { logger } from \"../logging\";\r\n\r\n/** Perf marker start suffix */\r\nconst StartMarkSuffix: string = \"-start\";\r\n\r\n/**\r\n * PerfMarker facilitates adding and measuring performance markers.\r\n */\r\nclass PerfMarker {\r\n /** The single instance of the PerfMarker class. */\r\n private static instance: PerfMarker;\r\n\r\n /** The performance object. */\r\n private performance: Performance;\r\n\r\n /** Perf marker end suffix */\r\n private readonly endMarkSuffix: string = \"-end\";\r\n\r\n /**\r\n * The constructor.\r\n */\r\n private constructor() {\r\n this.initialize(performance);\r\n }\r\n\r\n /**\r\n * Returns singleton class instance.\r\n * @returns The class instance\r\n */\r\n public static getInstance(): PerfMarker {\r\n if (!PerfMarker.instance) {\r\n PerfMarker.instance = new PerfMarker();\r\n }\r\n\r\n return PerfMarker.instance;\r\n }\r\n\r\n /**\r\n * Initialize the member variables.\r\n * @param performance - The performance object instance.\r\n */\r\n public initialize(performance: Performance): void {\r\n this.performance = performance;\r\n }\r\n\r\n /**\r\n * Adds given perf marker to browser.\r\n * @param name - Perf marker to start\r\n */\r\n public startMark(name: string): void {\r\n this.singleMark(name + StartMarkSuffix);\r\n }\r\n\r\n /**\r\n * Adds given perf marker to browser.\r\n * @param name - Perf marker to end\r\n */\r\n public endMark(name: string): void {\r\n this.singleMark(name + this.endMarkSuffix);\r\n this.measureStartEnd(name);\r\n }\r\n\r\n /**\r\n * Adds a single performance marker via the performance API.\r\n * @param name - the name of the perf marker\r\n */\r\n public singleMark(name: string): void {\r\n let performance = this.performance;\r\n if (performance && performance.mark) {\r\n performance.mark(name);\r\n }\r\n }\r\n\r\n /**\r\n * Utility method to add start/end marker around a promise.\r\n * @param name - The name of perf marker\r\n * @param getPromise - The callback\r\n * @returns The promise\r\n */\r\n public async measurePromise(name: string, getPromise: () => Promise): Promise {\r\n this.startMark(name);\r\n let result = await getPromise();\r\n this.endMark(name);\r\n return result;\r\n }\r\n\r\n /**\r\n * Telemetry call this method to collect existing perf markers that each Experience has added.\r\n * @param experienceName - Perf marker name in case of custom marker / Experience name\r\n * @returns {IPerfMarkers}\r\n */\r\n public measurePerfMarker(experienceName: string): IPerfMarkers {\r\n\r\n if (!this.performance) {\r\n return;\r\n }\r\n\r\n let perfMarkers: { [id: string]: PerfMarkerDetail; } = {};\r\n\r\n // Get all perf markers from browser.\r\n let perfEntries = this.performance.getEntriesByType(\"mark\");\r\n if (!perfEntries) {\r\n return perfMarkers;\r\n }\r\n\r\n // Iterate through perfEntries received from browser.\r\n for (let i = 0; i < perfEntries.length; i++) {\r\n\r\n // if marker name in perfEntries object is null\r\n let markerName: string = perfEntries[i].name;\r\n if (!markerName || perfEntries[i].startTime == null) {\r\n continue;\r\n }\r\n\r\n // Remove start and end suffix.\r\n markerName = markerName.replace(/-(end|start)$/i, \"\");\r\n\r\n // if marker name retrieved from browser is not for this experience then continue with next marker.\r\n if (!markerName.startsWith(experienceName)) {\r\n continue;\r\n }\r\n\r\n let perfMarkerDetail = perfMarkers[markerName] || new PerfMarkerDetail(markerName);\r\n perfMarkerDetail.processPerfEntry(perfEntries[i]);\r\n if (perfMarkerDetail.isValid) {\r\n perfMarkers[markerName] = perfMarkerDetail;\r\n }\r\n }\r\n\r\n return perfMarkers;\r\n }\r\n\r\n /**\r\n * Measures the given marker name's start/end markers.\r\n * @param name - The name of the marker whose -start and -end to measure\r\n */\r\n private measureStartEnd(name: string): void {\r\n let performance = this.performance;\r\n if (performance && performance.measure) {\r\n try {\r\n performance.measure(\r\n name,\r\n name + StartMarkSuffix,\r\n name + this.endMarkSuffix\r\n );\r\n } catch (ex) {\r\n // An exception will be thrown if either start/end marker didn't exist.\r\n // We swallo this exception and log an error so that actual code's execution\r\n // would not be effected due to performance measurement code.\r\n logger.logError(`Error while attempting to measure start/end of '${name}'. Error: ${ex}`);\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport const perfMarker = PerfMarker.getInstance();\r\n\r\n/**\r\n * Interface defining attributes of each per marker.\r\n */\r\nexport interface IPerfMarkers {\r\n [key: string]: PerfMarkerDetail;\r\n}\r\n\r\n/**\r\n * Interface defining perf markers.\r\n */\r\nclass PerfMarkerDetail {\r\n /** marker name */\r\n public readonly markerName: string;\r\n /** first start time */\r\n public firstStartTime: number;\r\n /** start time */\r\n public startTime: number;\r\n /** duration */\r\n public duration: number = 0;\r\n\r\n /**\r\n * Sets marker name.\r\n */\r\n constructor(markerName: string) {\r\n this.markerName = markerName;\r\n }\r\n\r\n /**\r\n * Check if given marker is valid. If marker has a start time then it is a valid marker.\r\n * @returns True if valid else false.\r\n */\r\n get isValid(): boolean {\r\n return this.startTime != null;\r\n }\r\n\r\n /**\r\n * Sum up start and end marker duraiton per marker name.\r\n */\r\n public processPerfEntry(perfEntry: PerformanceEntry): void {\r\n\r\n // If given mark is a start mark\r\n if (perfEntry.name.endsWith(StartMarkSuffix)) {\r\n\r\n // If this is a start mark and firstStartTime is undefined then assign value of startTime now.\r\n if (!this.firstStartTime) {\r\n this.firstStartTime = perfEntry.startTime;\r\n }\r\n\r\n // Change start time to start time of current mark.\r\n this.startTime = perfEntry.startTime;\r\n\r\n } else if (this.startTime != null) {\r\n // This is is not a start mark. Assuming this is end mark, check start time of this mark is set earlier. if set properly then proceed.\r\n // else likely a candiddate to skip \"if\" part.\r\n\r\n // This is a end mark. Add earlier duration plus current start time minus this start time.\r\n this.duration += perfEntry.startTime - this.startTime;\r\n\r\n // reset start time so we can recalculate the next start/end pair correctly\r\n this.startTime = null;\r\n }\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { HeadingProps } from \"@microsoft/fast-components-react-msft\";\r\n\r\n/**\r\n * An enum for intra article component position values\r\n *\r\n * @export\r\n * @enum IntraArticleComponentPosition\r\n */\r\nexport enum IntraArticleComponentPosition {\r\n Normal = \"normal\",\r\n Wide = \"wide\"\r\n}\r\n\r\n/**\r\n * An enum for views article component types\r\n *\r\n * @export\r\n * @enum IntraArticleComponentType\r\n */\r\nexport enum IntraArticleComponentType {\r\n ArticleReader = \"articlereader\",\r\n InlineImage = \"inlineimage\",\r\n InlineSlideshow = \"inlineslideshow\",\r\n InlineVideo = \"inlinevideo\",\r\n FacebookEmbed = \"facebookembed\",\r\n TwitterEmbed = \"twitterembed\",\r\n InstagramEmbed = \"instagramembed\",\r\n GiphyEmbed = \"giphyembed\",\r\n GraphiqEmbed = \"graphiqembed\",\r\n PinterestEmbed = \"pinterestembed\",\r\n TextParagraph = \"textparagraph\",\r\n Unknown = \"unknown\"\r\n}\r\n\r\n/**\r\n * An interface for SocialEmbedData contract\r\n *\r\n * @export\r\n * @interface SocialEmbedData\r\n */\r\nexport interface SocialEmbedData {\r\n /**\r\n * Social feed attribution\r\n * @type {string}\r\n */\r\n attribution?: string;\r\n\r\n /**\r\n * Url to fetch social feed from provider\r\n * @type {string}\r\n */\r\n feedHref: string;\r\n\r\n /**\r\n * Embed identifier\r\n * @type {string}\r\n */\r\n id: string;\r\n\r\n /**\r\n * Title for the social feed\r\n * @type {string}\r\n */\r\n title?: string;\r\n\r\n /**\r\n * Social embed type\r\n * @type {IntraArticleComponentType}\r\n */\r\n type: IntraArticleComponentType;\r\n}\r\n\r\n/**\r\n * An interface for IntraArticleComponent contract\r\n *\r\n * @export\r\n * @interface IntraArticleComponent\r\n */\r\nexport interface IntraArticleComponent {\r\n /**\r\n * CMS document id\r\n * @type {string}\r\n */\r\n cmsDocumentId?: string;\r\n\r\n /**\r\n * Additional component data\r\n * @type {unknown}\r\n */\r\n data?: unknown;\r\n\r\n /**\r\n * Message to show if error encountered while loading component\r\n * @type {HeadingProps}\r\n */\r\n loadError?: HeadingProps;\r\n\r\n /**\r\n * Ingested component markup\r\n * @type {string}\r\n */\r\n marker: string;\r\n\r\n /**\r\n * Position index in ingested article body markup\r\n * @type {number}\r\n */\r\n startIndex: number;\r\n\r\n /**\r\n * Expected component positioning inside article body\r\n * @type {IntraArticleComponentPosition}\r\n */\r\n position?: IntraArticleComponentPosition;\r\n\r\n /**\r\n * Type of component\r\n * @type {IntraArticleComponentType}\r\n */\r\n type: IntraArticleComponentType;\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { requireAsync } from \"./RequireAsync\";\r\n\r\n/**\r\n * Integration function to retrieve the prime track object.\r\n *\r\n * @export\r\n * @return {Promise} - Resolves if the track object could be loaded, rejects otherwise.\r\n */\r\nexport let getTrack: IGetTrack = () => {\r\n return requireAsync(\"track\");\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { requireAsync } from \"./RequireAsync\";\r\n\r\n/**\r\n * Integration function to retrieve the prime mediator object.\r\n *\r\n * @export\r\n * @return {Promise} - Resolves with the mediator if it could be loaded, rejects otherwise.\r\n */\r\nexport let getMediator: IGetMediator = () => {\r\n return requireAsync(\"mediator\");\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { requireAsync } from \"./RequireAsync\";\r\n\r\n/**\r\n * Integration function to wait on track extension complete canary.\r\n *\r\n * @export\r\n * @return {Promise} - Resolves if track extension canary is define, rejects otherwise.\r\n */\r\nexport let getTrackExtCompleteCanary: IGetTrackExtComplete = () => {\r\n return requireAsync(\"c.trackExtComplete\");\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { getTrack } from \"./PrimeTrack\";\r\nimport { getTrackExtCompleteCanary } from \"./PrimeTrackExtensionComplete\";\r\nimport { getTrackInfo } from \"./PrimeTrackInfo\";\r\nimport { AppError } from \"@msnews/diagnostics\";\r\n\r\ntype trackingEventCall = {event: Event, element: HTMLElement, destination: string, headline: string};\r\ntype trackPartialImpression = {elem?: HTMLElement, visibilityCheck?: boolean, mechanism?: TrackMechanism, topLevelContainerType?: string};\r\n\r\nlet trackingResolved: boolean = false;\r\nlet trackingObject: PrimeGlobal.ITrack = null;\r\nlet trackExtCompleted: any = null;\r\nlet trackEventBuffer: trackingEventCall[] = [];\r\nlet trackImpressionBuffer: trackPartialImpression[] = [];\r\nlet trackAppErrorEventBuffer: AppError[] = [];\r\nlet trackingPromiseCalled: boolean = false;\r\n\r\n// Following code is to decouple Prime dependency from initial state of experience. Once tracking is ported to Peregrine, it would not be needed.\r\n/**\r\n * Send the tracking call\r\n * @param {Event} event event object\r\n * @param {HTMLElement} element form code\r\n * @param {string} destination text\r\n * @param {string} headline text\r\n * @void\r\n */\r\nfunction sendTrackingCall(event: Event, element: HTMLElement, destination: string, headline: string): void {\r\n trackingObject.trackEvent(event, element, destination, headline);\r\n}\r\n\r\n/**\r\n * Makes the partial page request\r\n * @param {HTMLElement} elem object\r\n * @param {boolean} visibilityCheck\r\n * @param {TrackMechanism} mechanism\r\n * @param {string} topLevelContainerType\r\n * @void\r\n */\r\nfunction sendPartialPageRequest(elem?: HTMLElement, visibilityCheck?: boolean, mechanism?: TrackMechanism, topLevelContainerType?: string): void {\r\n trackingObject.trackPartialImpression(elem, visibilityCheck, mechanism, topLevelContainerType);\r\n}\r\n\r\n/**\r\n * Converts the AppError object to the Prime AppError type and make the trackAppErrorEvent call\r\n * @param appError - App error object\r\n */\r\nfunction sendTrackAppErrorEvent(appError: AppError): void {\r\n trackingObject.trackAppErrorEvent({ errId: appError.id, errSource: appError.source, errMsg: appError.message });\r\n}\r\n\r\n/**\r\n * Processes the pending tracking and page impresssion calls for statics.\r\n * Dependencies: getTrack(), getTrackExtCompleteCanary()\r\n * @void\r\n */\r\nfunction processPendingTrackingCall(): void {\r\n Promise.all([getTrack(), getTrackExtCompleteCanary()])\r\n .then(modules => {\r\n [trackingObject, trackExtCompleted] = modules;\r\n\r\n // at this point we will process any pending requests and resolve tracking\r\n trackingResolved = true;\r\n if (trackEventBuffer.length > 0) {\r\n trackEventBuffer.forEach(eventObj => {\r\n try {\r\n sendTrackingCall(eventObj.event, eventObj.element, eventObj.destination, eventObj.headline);\r\n } catch {\r\n // This catch block is meant to continue to next element in the loop.\r\n // We may remove this in future once Error Boundaries are added.\r\n }\r\n });\r\n\r\n // empty it again after processing\r\n trackEventBuffer = [];\r\n }\r\n\r\n if (trackImpressionBuffer.length > 0) {\r\n trackImpressionBuffer.forEach(eventObj => {\r\n sendPartialPageRequest(eventObj.elem, eventObj.visibilityCheck, eventObj.mechanism, eventObj.topLevelContainerType);\r\n });\r\n\r\n // empty it again after processing\r\n trackImpressionBuffer = [];\r\n }\r\n\r\n if (trackAppErrorEventBuffer.length > 0) {\r\n trackAppErrorEventBuffer.forEach(appError => {\r\n sendTrackAppErrorEvent(appError);\r\n });\r\n\r\n // empty it again after processing\r\n trackAppErrorEventBuffer = [];\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Callback function to pass to experience. It maintains an internal array to hold track calls until dependencies resolved.\r\n * @param {Event} event event object\r\n * @param {HTMLElement} element form code\r\n * @param {string} destination text\r\n * @param {string} headline text\r\n * @void\r\n */\r\nexport function handleTelemetryCall(event: Event, element: HTMLElement, destination: string, headline: string): void {\r\n if (trackingResolved) {\r\n sendTrackingCall(event, element, destination, headline);\r\n } else {\r\n trackEventBuffer.push({ event: event, element: element, destination: destination, headline: headline });\r\n\r\n if (!trackingPromiseCalled) {\r\n trackingPromiseCalled = true;\r\n\r\n // only want to call this once\r\n processPendingTrackingCall();\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Makes the partial page request\r\n * @param {HTMLElement} elem object\r\n * @param {boolean} visibilityCheck\r\n * @param {TrackMechanism} mechanism\r\n * @param {string} topLevelContainerType\r\n * @void\r\n */\r\nexport function handlePartialPageImpressionCall(elem?: HTMLElement, visibilityCheck?: boolean, mechanism?: TrackMechanism, topLevelContainerType?: string): void {\r\n if (trackingResolved) {\r\n sendPartialPageRequest(elem, visibilityCheck, mechanism, topLevelContainerType);\r\n } else {\r\n trackImpressionBuffer.push({ elem: elem, visibilityCheck: visibilityCheck, mechanism: mechanism, topLevelContainerType: topLevelContainerType });\r\n\r\n if (!trackingPromiseCalled) {\r\n trackingPromiseCalled = true;\r\n\r\n // only want to call this once\r\n processPendingTrackingCall();\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Handler to log app errors\r\n * @param appError - App error object\r\n * @void\r\n */\r\nexport function handleAppErrorEventCall(appError: AppError): void {\r\n if (trackingResolved) {\r\n sendTrackAppErrorEvent(appError);\r\n } else {\r\n trackAppErrorEventBuffer.push({ ...appError });\r\n if (!trackingPromiseCalled) {\r\n trackingPromiseCalled = true;\r\n\r\n // only want to call this once\r\n processPendingTrackingCall();\r\n }\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { endsWith as _endsWith, some as _some } from \"lodash-es\";\r\n\r\nimport { IActionMap } from \"./IActionMap\";\r\nimport { IActionPayload } from \"./IActionPayload\";\r\nimport { String as StringOperations } from \"typescript-string-operations\";\r\n\r\n/**\r\n * Class Contains helpers to use inside of a reducer, that is managed by and called from DynamicReducer\r\n * These helpers provide the ability to use a strongly typed callback that matches the parameters of an Action.\r\n * redux-subspace will automatically prepend a namespace to actions so that they are targeted to their specific subspace.\r\n * DynamicReducer already handles ensuring actions reach the correct reducer, so the redux-subspace namespace can be ignored\r\n * @class\r\n */\r\nexport class ActionHandler {\r\n\r\n /**\r\n * local function that either uses the built-in String.prototype.endsWith function, or uses the lodash-es function to polyFill;\r\n * the built-in function is significantly faster than the lodash-es function or other options, so we want to use it when we can;\r\n * the lodash-es function, based on splice, is faster than String.prototype.indexOf, but using RegEx might be faster...\r\n */\r\n private static endsWith: Function = String.prototype.endsWith\r\n ? function (search: string, target: string): boolean { return search.endsWith(target); }\r\n : _endsWith;\r\n\r\n /**\r\n * Method to handle specific actions.\r\n * @method\r\n * @param actionPayload {IActionPayload} The action details.\r\n * @param actionMap {IActionMap} The actionMap which maps Action to its callback function type.\r\n * @param callback {TActionSignature} function of type TActionSignature.\r\n * @return { boolean } true if the action type matched, false otherwise.\r\n */\r\n public static handleAction(\r\n actionPayload: IActionPayload,\r\n actionMap: IActionMap,\r\n callback: TActionSignature): boolean {\r\n\r\n // actionPayload.type may have a redux-subspace namespace prepended, so check to see if the ending action is what we want\r\n // namespaces are separated from the action type by a \"/\";\r\n // we use that to differentiate where the payload type ends with the mapped type as part of the name, but is not the same action\r\n // e.g. \"Action\" in the action map and \"NameSpace/AnotherAction\" in the payload, both end in \"Action\" but do not match\r\n // we prepend to *both* to cover the case where they are already equal (that is, no namespace is present)\r\n\r\n if (ActionHandler.endsWith(actionPayload.type + \"\", actionMap.type)) {\r\n callback.apply(callback, actionPayload.params);\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Method to handle multiple actions with same signature.\r\n * @method\r\n * @param actionPayload {IActionPayload} The action details.\r\n * @param actionMap {IActionMap[]} The collection of actionMaps which maps Action to its callback function type.\r\n * @param callback {TActionSignature} function of type TActionSignature.\r\n * @return { boolean } true if the action type matched, false otherwise.\r\n */\r\n public static handleActions(\r\n actionPayload: IActionPayload,\r\n actionMaps: IActionMap[],\r\n callback: TActionSignature): boolean {\r\n\r\n const actionPayloadType = actionPayload.type + \"\";\r\n let actionsMatched = _some(actionMaps, (actionMap) => ActionHandler.endsWith(actionPayloadType, actionMap.type));\r\n\r\n if (actionsMatched) {\r\n callback.apply(callback, actionPayload.params);\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Method to handle specific actions and check typescript type safely.\r\n * It throws error if actionMap.type does not equal the actionPayload.type.\r\n * @method\r\n * @param actionPayload {IActionPayload} The action details.\r\n * @param actionMap {IActionMap} The actionMap which maps Action to its callback function type.\r\n * @param callback {TActionSignature} function of type TActionSignature.\r\n * @return { boolean } true if the action type matched, false otherwise.\r\n */\r\n public static safeHandleAction(\r\n actionPayload: IActionPayload,\r\n actionMap: IActionMap,\r\n callback: TActionSignature): any {\r\n\r\n if (!ActionHandler.endsWith(actionPayload.type + \"\", actionMap.type)) {\r\n throw \"The action payload does not match the action type.\";\r\n }\r\n\r\n callback.apply(callback, actionPayload.params);\r\n return true;\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Set of resource string used by article reader components\r\n */\r\nconst ViewsStringResource = {\r\n article: \"article\",\r\n image: \"image\",\r\n video: \"video\",\r\n gallery: \"gallery\",\r\n exitFullscreen: \"Exit Full Screen\",\r\n fullscreen: \"Full Screen\",\r\n nextSlide: \"Next Slide\",\r\n previousSlide: \"Previous Slide\",\r\n publishedSecondAgo: \"second ago\",\r\n publishedSecondsAgo: \"seconds ago\",\r\n publishedMinuteAgo: \"minute ago\",\r\n publishedMinutesAgo: \"minutes ago\",\r\n publishedHourAgo: \"hr ago\",\r\n publishedHoursAgo: \"hrs ago\",\r\n publishedDayAgo: \"day ago\",\r\n publishedDaysAgo: \"days ago\",\r\n gallerySlideError: \"Something went wrong while loading this slide.\",\r\n sharingToolbarLoadFailure: \"Failed to render sharing toolbar.\",\r\n invalidCMSIdErrorFormat: \"Invalid {0} document. Please try a different one.\",\r\n documentDataFetchErrorFormat: \"Whoops! This {0} doesn’t exist or can’t be found. Please try a different one.\",\r\n intraArticleComponentErrorFormat: \"This {0} doesn’t exist or can’t be found.\",\r\n gallerySlideCountFormat: \"{0}/{1} SLIDES\",\r\n gallerySlideCountFullScreenFormat: \"{0} of {1}\",\r\n seeOnProviderSite: \"See on {0}\",\r\n socialFeedNotSupported: \"Social media feed type not supported.\",\r\n articleReadMoreText: \"show more\"\r\n};\r\n\r\nexport { ViewsStringResource };","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { isNil, isString, omitBy } from \"lodash-es\";\r\n\r\nimport { TelemetryOrdinalTracker } from \"./Telemetry.OrdinalTracker\";\r\nimport { TelemetryProps } from \"./Telemetry.props\";\r\nimport { TelemetryTags } from \"./Telemetry.tags\";\r\nimport { TelemetryTypes } from \".\";\r\nimport { Utility } from \"@msnews/core\";\r\n\r\n/**\r\n * Telemetry class to inject into components via props.\r\n *\r\n * @export\r\n * @class Telemetry\r\n */\r\nexport class Telemetry {\r\n\r\n /**\r\n * The index to uniquely identify the telemetry elements.\r\n * @private\r\n * @type {number}\r\n */\r\n public static ordinalTracker: { [id: number]: TelemetryOrdinalTracker } = {\r\n 0: {\r\n childIndices: [],\r\n childOrdinalCounter: 0,\r\n ordinal: 1\r\n }\r\n };\r\n\r\n /**\r\n * The index to uniquely identify the telemetry elements.\r\n * @private\r\n * @type {number}\r\n */\r\n public static telemetryIndex: number = 0;\r\n\r\n /**\r\n * Set the new telemetry props for a child component.\r\n * @type {function}\r\n * @param {parentTelemetry} telemetry - props that may contain the telemetry index of the parent component.\r\n * @param {childTelemetry} telemetry - props that contain the telemetry index of the child component.\r\n */\r\n public static setChildProps(parentTelemetry: TelemetryProps, childTelemetry: TelemetryProps): void {\r\n if (!parentTelemetry) {\r\n throw \"the parentTelemetry parameter is required\";\r\n }\r\n\r\n if (!childTelemetry) {\r\n throw \"the childTelemetry parameter is required\";\r\n }\r\n\r\n // set parentIndex from parent's index; if the parent has no non-zero index, use the grandparent index instead, falling back to zero\r\n childTelemetry.parentIndex = parentTelemetry.index || parentTelemetry.parentIndex || 0;\r\n\r\n // This part is required to trigger shouldComponentUpdate on child component,\r\n // if no other props changed but parent component re-renders.\r\n // childTelemetryProps.headlineIndex = Math.random();\r\n }\r\n\r\n /**\r\n * Gets the telemetry item for a child element.\r\n *\r\n * @static\r\n * @param {TelemetryProps} parentTelemetry the telemetry props for the parent element\r\n * @param {string} telemetryName the telemetry name for the child\r\n * @param {TelemetryTypes} telemetryType the telemetry type for the child\r\n * @returns {TelemetryProps} the telemetry props for the child\r\n * @memberof Telemetry\r\n */\r\n public static getChildTelemetryItem(parentTelemetry: TelemetryProps, telemetryName: string, telemetryType: TelemetryTypes): TelemetryProps {\r\n const initTelemetryProps: TelemetryProps = {\r\n name: telemetryName,\r\n telemetryType: telemetryType\r\n };\r\n\r\n const resultTelemetryProps = Telemetry.createProps(initTelemetryProps, parentTelemetry, initTelemetryProps);\r\n Telemetry.setChildProps(parentTelemetry, resultTelemetryProps);\r\n\r\n return resultTelemetryProps;\r\n }\r\n\r\n /**\r\n * Get the parent's index value for telemetry.\r\n * @type {function}\r\n * @param {parentTelemetry} telemetry - props that may contain the telemetry index of the parent component.\r\n */\r\n public static getParentIndex(parentTelemetry: TelemetryProps): number {\r\n if (!parentTelemetry) {\r\n throw \"the parentTelemetry parameter is required\";\r\n }\r\n\r\n // return parentIndex from parent's index; if the parent has no non-zero index, use the grandparent index instead, even if zero\r\n return parentTelemetry.index || parentTelemetry.parentIndex;\r\n }\r\n\r\n /**\r\n * Get the parent's index value for telemetry.\r\n * @type {function}\r\n * @param {parentTelemetry} telemetry - props that may contain the telemetry index of the parent component.\r\n */\r\n public static getParentHeadlineIndex(parentTelemetry: TelemetryProps): number {\r\n if (!parentTelemetry) {\r\n throw \"the parentTelemetry parameter is required\";\r\n }\r\n\r\n // This part is required to trigger shouldComponentUpdate on child component,\r\n // if no other props changed but parent component re-renders.\r\n return Math.random();\r\n }\r\n\r\n /**\r\n * Create the root private telemetry object for an application\r\n * @type {function}\r\n * @param {string} name - Name of the entity.\r\n * @param {string} id - Id property of the entity.\r\n * @param {number} rootTelemetryIndex - telemetry index of root, e.g. the SPA host container index\r\n * @returns {TelemetryProps} - private Telemetery props\r\n */\r\n public static createRootProps(name?: string, id?: string, rootTelemetryIndex?: number): TelemetryProps {\r\n const ordinal = 0;\r\n\r\n // root index if specified otherwise we set it the next telemetry index\r\n const rootIndex = rootTelemetryIndex || Telemetry.getNewIndex();\r\n\r\n Telemetry.ordinalTracker[rootIndex] = {\r\n ordinal,\r\n childIndices: {},\r\n childOrdinalCounter: 0\r\n };\r\n\r\n return {\r\n id: id,\r\n index: rootIndex,\r\n name: name,\r\n ordinal: ordinal,\r\n parentIndex: 0\r\n };\r\n }\r\n\r\n /**\r\n * Create the telemetry object for the component.\r\n * @type {function}\r\n * @param {TelemetryProps} savedProps - Props that are being saved by the calling component. If this is the first call to createProps, null or undefined should be passed.\r\n * @param {TelemetryProps} componentProps - Props that were passed into the calling component. This set of props carries the parentIndex.\r\n * @param {TelemetryProps} initializationProps - Override props which can be used to replace the default properties\r\n * @returns {TelemetryProps} - Telemetry props\r\n */\r\n public static createProps(savedProps: TelemetryProps, componentProps: TelemetryProps, initializationProps: TelemetryProps = {}): TelemetryProps {\r\n\r\n const parentIndex = componentProps.parentIndex || 0;\r\n\r\n if (!(parentIndex in Telemetry.ordinalTracker)) {\r\n throw \"parentIndex not tracked in ordinalTracker\";\r\n }\r\n\r\n let index: number;\r\n let ordinal: number;\r\n\r\n // TODO are we calling the right one?\r\n if (savedProps && !isNil(savedProps.index)) {\r\n index = savedProps.index;\r\n } else {\r\n index = Telemetry.getNewIndex();\r\n }\r\n\r\n Telemetry.resetChildProps(index);\r\n\r\n let isIndexTrackedByParent: boolean = index in Telemetry.ordinalTracker[parentIndex].childIndices;\r\n if (isIndexTrackedByParent) {\r\n ordinal = Telemetry.ordinalTracker[parentIndex].childIndices[index];\r\n } else {\r\n ordinal = ++Telemetry.ordinalTracker[parentIndex].childOrdinalCounter;\r\n Telemetry.ordinalTracker[parentIndex].childIndices[index] = ordinal;\r\n }\r\n\r\n Telemetry.ordinalTracker[index] = {\r\n ordinal,\r\n childIndices: {},\r\n childOrdinalCounter: 0\r\n };\r\n\r\n return { ...initializationProps, index, ordinal, parentIndex };\r\n }\r\n\r\n /**\r\n * Render telemetry props to the DOM.\r\n * @type {function}\r\n * @param {TelemetryProps} props - Props of the element which needs to render telemetry string.\r\n * @returns {TelemetryTags} - Telemetery tags for rendering\r\n */\r\n public static render(props: TelemetryProps): TelemetryTags {\r\n if (!props || !props.index) {\r\n return null;\r\n }\r\n\r\n const result: any = {\r\n c: props.category,\r\n ct: props.contentType,\r\n f: props.feedId || props.id,\r\n h: props.headlineIndex,\r\n i: props.index,\r\n l: props.id,\r\n n: props.name,\r\n o: props.ordinal,\r\n p: props.parentIndex,\r\n y: props.telemetryType,\r\n v: props.vertical\r\n };\r\n\r\n const filteredResult = omitBy(result, isNil);\r\n\r\n const tags: TelemetryTags = {\r\n \"data-m\": JSON.stringify(filteredResult),\r\n \"data-id\": filteredResult.i\r\n };\r\n\r\n if (isString(props.userFacingText)) {\r\n tags[\"data-hl\"] = props.userFacingText;\r\n }\r\n\r\n return tags;\r\n }\r\n\r\n // Bug 15830025: if this isn't used, we should delete it; if it is used, it needs unit tests.\r\n /**\r\n * Resets the global dictionary recursively starting at the given component.\r\n * @type {function}\r\n * @param {number} telemetryIndex - Telemetry index of the component.\r\n */\r\n public static resetChildProps(telemetryIndex: number): void {\r\n if (!(telemetryIndex in Telemetry.ordinalTracker)) {\r\n return;\r\n }\r\n\r\n const childIndices = Telemetry.ordinalTracker[telemetryIndex].childIndices;\r\n Object.keys(childIndices).map((index) => this.resetChildProps(Utility.toNumber(index)));\r\n delete Telemetry.ordinalTracker[telemetryIndex];\r\n }\r\n\r\n /**\r\n * Decides if the new telemetry related props changed on parent component.\r\n * @type {function}\r\n * @param {TelemetryProps} oldProps - Old props of the element which contains parentIndex and ordinal values.\r\n * @param {TelemetryProps} newProps - New props of the element which contains parentIndex and ordinal values.\r\n * @param {TelemetryProps} telemetry - Existing private telemetry props of the element.\r\n * @returns {boolean} - should telemetry props need to be changed.\r\n */\r\n public static shouldComponentUpdate(oldProps: TelemetryProps, newProps: TelemetryProps, telemetry: TelemetryProps): boolean {\r\n return (oldProps.parentIndex !== newProps.parentIndex)\r\n || (telemetry && !(telemetry.index in Telemetry.ordinalTracker[oldProps.parentIndex].childIndices));\r\n }\r\n\r\n /**\r\n * Creates and returns new telemetry index which should be global among the application.\r\n *\r\n * @export\r\n * @return {number}\r\n */\r\n private static getNewIndex(): number {\r\n return --Telemetry.telemetryIndex;\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n// TODO: This should be considered for moving it to the Interests experience wrapper, once that\r\n// code arrives, since this is specific to that experience\r\n\r\n/**\r\n * Tab Names\r\n * @export\r\n * @type {object}\r\n */\r\nexport const SubnavTabName = {\r\n Interests: \"cinterests\",\r\n MyFeed: \"newsfeed\",\r\n XFeed: \"xfeed\"\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ImageServiceConfig, KeyValueArray, UrlUtility, getAppEnvironment } from \"@msnews/core\";\r\nimport { Telemetry, TelemetryProps, TelemetryTypes } from \"@msnews/experiences-base\";\r\n\r\nimport { TelemetryBase } from \"@msnews/core\";\r\nimport { ViewsCommonAppErrors } from \"@msnews/diagnostics\";\r\nimport { ViewsStringResource } from \"./\";\r\nimport { format } from \"@microsoft/fast-web-utilities\";\r\n\r\n/**\r\n * Image resize mode enum\r\n */\r\nexport enum ImageResizeMode {\r\n /**\r\n * Default value but the Image Resizer actually replaces it by the scale option (2)\r\n */\r\n None = \"0\",\r\n\r\n /**\r\n * Maintains aspect ratio as letter box\r\n */\r\n Letterbox = \"1\",\r\n\r\n /**\r\n * Maintains aspect ratio\r\n */\r\n\r\n Scale = \"2\",\r\n\r\n /**\r\n * Stretches image to fit height and width\r\n */\r\n Stretch = \"3\",\r\n\r\n /**\r\n * Crops image to fit height and width\r\n */\r\n\r\n Crop = \"4\",\r\n\r\n /**\r\n * Crops the image using focal points\r\n */\r\n FocalCrop = \"5\",\r\n\r\n /**\r\n * Crop the image using a face auto-detection technique.\r\n */\r\n FacialCrop = \"6\"\r\n}\r\n\r\n/**\r\n * An interface for ImageResizeOptions contract\r\n *\r\n * @export\r\n * @interface ImageResizeOptions\r\n */\r\nexport interface ImageResizeOptions {\r\n\r\n /**\r\n * Letter-boxing an image while performing a resize.\r\n * This is only applicable to Facial Crop Mode and Focal-cropping is disabled\r\n */\r\n LetterBoxing?: boolean;\r\n\r\n /**\r\n * Focal-cropping (around a facial area) while performing a resize.\r\n * This is only applicable to Facial Crop Mode\r\n */\r\n FocalCropping?: boolean;\r\n\r\n /**\r\n * Background color is used to fill in the remaining region\r\n * This is only applicable to Letter-Box Mode\r\n */\r\n BackgroundColor?: string;\r\n}\r\n\r\n/**\r\n * An interface for ImageFocalRegion contract\r\n *\r\n * @export\r\n * @interface ImageFocalRegion\r\n */\r\nexport interface ImageFocalRegion {\r\n /**\r\n * the first point's x position of the focal point in an image.\r\n */\r\n x1?: number;\r\n\r\n /**\r\n * the second point's x position of the focal point in an image\r\n */\r\n x2?: number;\r\n\r\n /**\r\n * the first point's y position of the focal point in an image\r\n */\r\n y1?: number;\r\n\r\n /**\r\n * the second point's y position of the focal point in an image\r\n */\r\n y2?: number;\r\n}\r\n\r\n/**\r\n * An interface for ViewsImageData contract\r\n *\r\n * @export\r\n * @interface ViewsImageData\r\n */\r\nexport interface ViewsImageData {\r\n /**\r\n * Alt text to te rendered for image\r\n */\r\n alt: string;\r\n\r\n /**\r\n * Image attribution details\r\n */\r\n attribution?: string;\r\n\r\n /**\r\n * Image caption\r\n */\r\n caption: string;\r\n\r\n /**\r\n * Image height in pixels\r\n */\r\n height?: number;\r\n\r\n /**\r\n * Image id\r\n */\r\n id?: string;\r\n\r\n /**\r\n * Image src url\r\n */\r\n src: string;\r\n\r\n /**\r\n * Image title\r\n */\r\n title?: string;\r\n\r\n /**\r\n * Image width in pixels\r\n */\r\n width?: number;\r\n}\r\n\r\n/**\r\n * An interface for ViewsUrlData contract\r\n *\r\n * @export\r\n * @interface ViewsUrlData\r\n */\r\nexport interface ViewsUrlData {\r\n /**\r\n * Document id\r\n */\r\n cmsId: string;\r\n\r\n /**\r\n * Namespace (ar or ss)\r\n */\r\n ns: string;\r\n\r\n /**\r\n * Locale\r\n */\r\n locale: string;\r\n\r\n /**\r\n * Document title\r\n */\r\n title?: string;\r\n\r\n /**\r\n * Vertial key\r\n */\r\n vertical: string;\r\n\r\n /**\r\n * Url sections\r\n */\r\n sections?: Array;\r\n\r\n /**\r\n * Query string\r\n */\r\n query?: string;\r\n}\r\n\r\n/**\r\n * Default image width to be used for resizing\r\n */\r\nexport const defaultImageWidth = 300;\r\n\r\n/**\r\n * Default image height to be used for resizing\r\n */\r\nexport const defaultImageHeight = 250;\r\n\r\n/**\r\n * Width for provider logo used in article/gallery header\r\n */\r\nexport const defaultProviderLogoWidth = 140;\r\n\r\n/**\r\n * Height for provider logo used in article/gallery header\r\n */\r\nexport const defaultProviderLogoHeight = 40;\r\n\r\n/**\r\n * Default image quality to be used for resizing\r\n */\r\nexport const defaultImageQuality = 100;\r\n\r\n/**\r\n * Default DPI\r\n */\r\nexport const defaultDpi = 1;\r\n\r\n/**\r\n * Compiled regex key for extracting html tags\r\n */\r\nexport const htmlTagsRegEx = new RegExp(\"<[^>]*>\", \"gim\");\r\n\r\n/**\r\n * Utility class for views components\r\n */\r\nexport const ViewsUtility = {\r\n\r\n /**\r\n * Ensure to return Views Image Data Object from given object\r\n * @returns {any} object\r\n */\r\n ensureViewsImageData(object: any): ViewsImageData {\r\n const imgObj = object || {};\r\n return {\r\n alt: imgObj.alt,\r\n attribution: imgObj.attribution,\r\n caption: imgObj.caption,\r\n title: imgObj.title,\r\n src: imgObj.src || imgObj.url\r\n };\r\n },\r\n\r\n /**\r\n * Compose image url\r\n * @param id Image Id\r\n * @param imageServiceUrl The base URL for loading CMS images via CDN\r\n * @param width Expected width\r\n * @param height Expected height\r\n * @returns {string} The image url\r\n */\r\n getImageUrl(\r\n id: string,\r\n width: number = defaultImageWidth,\r\n height: number = defaultImageHeight,\r\n imageServiceUrl: string = ImageServiceConfig.prod): string {\r\n\r\n if (!id) {\r\n return null;\r\n }\r\n\r\n return `${imageServiceUrl}${id}?w=${width}&h=${height}&q=60&m=6&u=t&o=t&l=f&f=jpg`;\r\n },\r\n\r\n /**\r\n * Append resizing params to image url\r\n *\r\n * @param image Image details\r\n * @param width Expected width\r\n * @param height Expected height\r\n * @param dpi DPI of device\r\n * @param resizeMode Image resize mode\r\n * @param quality Quality of the resized image in percentage (100 means 100%)\r\n * @param options Image resize options\r\n * @returns {string} The updated image url\r\n */\r\n getResizedImageUrl(\r\n image: ViewsImageData,\r\n width: number = defaultImageWidth,\r\n height: number = defaultImageHeight,\r\n dpi: number = defaultDpi,\r\n resizeMode: ImageResizeMode = ImageResizeMode.None,\r\n quality: number = defaultImageQuality,\r\n options: ImageResizeOptions = null,\r\n focalRegion: ImageFocalRegion = null): string {\r\n if (image && image.src) {\r\n let opts = \"\";\r\n\r\n if (options) {\r\n if (options.LetterBoxing !== undefined) {\r\n opts += \"&l=\" + (options.LetterBoxing === true ? \"t\" : \"f\");\r\n }\r\n\r\n if (options.FocalCropping !== undefined) {\r\n opts += \"&o=\" + (options.FocalCropping === true ? \"t\" : \"f\");\r\n }\r\n\r\n if (options.BackgroundColor !== undefined) {\r\n opts += \"&b=\" + options.BackgroundColor;\r\n }\r\n }\r\n\r\n if (focalRegion) {\r\n let x = 0;\r\n let y = 0;\r\n\r\n if (focalRegion.x1 === focalRegion.x2 && focalRegion.y1 === focalRegion.y2) {\r\n x = focalRegion.x1;\r\n y = focalRegion.y1;\r\n } else {\r\n x = focalRegion.x1 + ((focalRegion.x2 - focalRegion.x1) / 2);\r\n y = focalRegion.y1 + ((focalRegion.y2 - focalRegion.y1) / 2);\r\n }\r\n\r\n if (x >= 0 && y >= 0) {\r\n opts += \"&x=\" + x + \"&y=\" + y;\r\n }\r\n }\r\n\r\n return `${image.src}?w=${width * dpi}&h=${height * dpi}&q=${quality}&m=${resizeMode}` + opts;\r\n }\r\n\r\n return null;\r\n },\r\n\r\n /**\r\n * Get the alt text of the image.\r\n *\r\n * @param {string} imageCaption The image caption\r\n * @param {string} altPrefix Text added to the ALT or used as a default\r\n * @returns {string} The image alt\r\n */\r\n getAltText(imageCaption: string, altPrefix: string = \"\"): string {\r\n if (!imageCaption) {\r\n return altPrefix;\r\n }\r\n\r\n // Decode and strip HTML tags\r\n const altText = ViewsUtility.stripHtmlTags(imageCaption);\r\n\r\n // Return the default alt text if the caption is null\r\n if (altText.length < 1) {\r\n return altPrefix;\r\n }\r\n\r\n // If the caption is already entirely contained within the alt text, then return the alt text\r\n if (altPrefix.includes(altText)) {\r\n return altPrefix;\r\n } else if (altText.indexOf(altPrefix) === 0) {\r\n // If the alt text is already the first few words of the caption, then use the caption\r\n return altText;\r\n }\r\n\r\n return `${altPrefix}: ${altText}`;\r\n },\r\n\r\n /**\r\n * Get the paragraph text with telemetry injected into partner links.\r\n *\r\n * @param {string} marker The marker text with placeholder eg: \r\n * @param {number} linksCount The total number of links with placeholder\r\n * @param {TelemetryProps} The telemetry props used to the placeholder\r\n * @returns {string} the text with telemetry on partner links\r\n */\r\n getParagraphText(marker: string, linksCount: number, telemetryProps: TelemetryProps): string {\r\n let markup = marker;\r\n if (markup && telemetryProps && linksCount > 0) {\r\n const partnerLinksCount = linksCount;\r\n let additionalProps: string[] = [];\r\n for (let i = 0; i < partnerLinksCount; i++) {\r\n const telemetry = Telemetry.render(ViewsUtility.getChildTelemetryItem(telemetryProps, \"partnerLink\", TelemetryTypes.Navigation));\r\n additionalProps.push(` data-m=${telemetry[\"data-m\"]} data-id=${telemetry[\"data-id\"]} target=\"_blank\" `);\r\n }\r\n markup = format(marker, ...additionalProps);\r\n }\r\n return markup || \"\";\r\n },\r\n\r\n /**\r\n * Helper to check if list is valid and non-empty\r\n * @param list List to check\r\n */\r\n safeAny(list: any[]): boolean {\r\n return list && list.length > 0;\r\n },\r\n\r\n /**\r\n * Helper for generating telemetry attributes from child elements\r\n * @param parentTelemetry Telemetry props of parent\r\n * @param telemetryName Telemetry name\r\n * @param telemetryType Telemetry type\r\n */\r\n getChildTelemetryItem(parentTelemetry: TelemetryProps, telemetryName: string, telemetryType: TelemetryTypes): TelemetryProps {\r\n const initTelemetryProps: TelemetryProps = {\r\n name: telemetryName,\r\n telemetryType: telemetryType\r\n };\r\n\r\n const resultTelemetryProps = Telemetry.createProps(initTelemetryProps, parentTelemetry, initTelemetryProps);\r\n Telemetry.setChildProps(parentTelemetry, resultTelemetryProps);\r\n return resultTelemetryProps;\r\n },\r\n\r\n /**\r\n * Generate friendly timestamp text based on document publish time\r\n *\r\n * @param dateTime Document publish date time\r\n * @returns {string} Friendly timestamp text\r\n * @returns {string} Locale specific friendly time stamp\r\n */\r\n getFriendlyTimestamp(dateTime: string): string {\r\n const currentTime = Date.now();\r\n const publishTime = Date.parse(dateTime);\r\n\r\n if (isNaN(publishTime)) {\r\n return;\r\n }\r\n\r\n const timeSpanInSeconds = Math.trunc((currentTime - publishTime) / 1000);\r\n if (timeSpanInSeconds > 0 && timeSpanInSeconds < 60) {\r\n return timeSpanInSeconds === 1 ? `${timeSpanInSeconds} ${ViewsStringResource.publishedSecondAgo}` : `${timeSpanInSeconds} ${ViewsStringResource.publishedSecondsAgo}`;\r\n }\r\n\r\n const timeSpanInMinutes = Math.trunc(timeSpanInSeconds / 60);\r\n if (timeSpanInMinutes > 0 && timeSpanInMinutes < 60) {\r\n return timeSpanInMinutes === 1 ? `${timeSpanInMinutes} ${ViewsStringResource.publishedMinuteAgo}` : `${timeSpanInMinutes} ${ViewsStringResource.publishedMinutesAgo}`;\r\n }\r\n\r\n const timeSpanInHours = Math.trunc(timeSpanInMinutes / 60);\r\n if (timeSpanInHours > 0 && timeSpanInHours < 24) {\r\n return timeSpanInHours === 1 ? `${timeSpanInHours} ${ViewsStringResource.publishedHourAgo}` : `${timeSpanInHours} ${ViewsStringResource.publishedHoursAgo}`;\r\n }\r\n\r\n const timeSpanInDays = Math.trunc(timeSpanInHours / 24);\r\n if (timeSpanInDays > 0 && timeSpanInDays < 7) {\r\n return timeSpanInDays === 1 ? `${timeSpanInDays} ${ViewsStringResource.publishedDayAgo}` : `${timeSpanInDays} ${ViewsStringResource.publishedDaysAgo}`;\r\n }\r\n\r\n const locale: string = getAppEnvironment().CurrentMarket;\r\n return new Date(dateTime).toLocaleDateString(locale);\r\n },\r\n\r\n /**\r\n * Get url data from url string\r\n * @param {string} url (eg: https://www.msn.com/en-us/news/politics/opinions-title/ar-BBTDXc5?li=AAggNb9)\r\n * @returns {ViewsUrlData} Url Data generated from url string\r\n */\r\n getViewsUrlData(url: string): ViewsUrlData {\r\n\r\n let result: ViewsUrlData = {\r\n cmsId: \"\",\r\n locale: \"\",\r\n vertical: \"\",\r\n ns: \"\"\r\n };\r\n\r\n if (UrlUtility.isValidUrl(url, true) === true) {\r\n let parser = document.createElement(\"a\");\r\n parser.href = url;\r\n\r\n if (parser.pathname.length > 0) {\r\n let parts = parser.pathname.split(\"/\");\r\n if (parts.length > 4) {\r\n result.locale = parts[1];\r\n result.vertical = parts[2];\r\n result.title = parts[parts.length - 2];\r\n let nsParts = parts[parts.length - 1].split(\"-\");\r\n if (nsParts.length === 2) {\r\n result.ns = nsParts[0];\r\n result.cmsId = nsParts[1];\r\n }\r\n\r\n if (parts.length > 4) {\r\n result.sections = parts[3].split(\"/\");\r\n }\r\n }\r\n }\r\n result.query = parser.search;\r\n }\r\n\r\n return result;\r\n },\r\n\r\n /**\r\n * Get the friendly title string that can be used in url path (eg: this-is-good-title-for-url)\r\n * @param {ViewsUrlData} title Incoming title\r\n * @returns {string} String of title from article or gallery (ie: This is good title)\r\n */\r\n getFriendlyTitleForUrl(title: string): string {\r\n if (!title) {\r\n return title;\r\n }\r\n\r\n const charReplaceTable: KeyValueArray = [\r\n { key: \"#\", value: \"number\" },\r\n { key: \"%\", value: \"percent\" },\r\n { key: \"&\", value: \"and\" },\r\n { key: \"+\", value: \"plus\" },\r\n { key: \"=\", value: \"equals\" },\r\n { key: \"$\", value: \"dollar\" },\r\n { key: \"©\", value: \"-c-\" },\r\n { key: \"®\", value: \"-r-\" },\r\n { key: \"™\", value: \"-tm-\" },\r\n { key: \"¼\", value: \"1-4\" },\r\n { key: \"½\", value: \"1-2\" },\r\n { key: \"¾\", value: \"3-4\" },\r\n { key: \"@\", value: \"-at-\" }\r\n ];\r\n\r\n const charRegExp = new RegExp(\"[\" + charReplaceTable.map(pair => { return pair.key; }).join(\"\") + \"]\", \"g\");\r\n const removeRegExp = new RegExp(\"[\" + \"\\\"<>*:.?^;`{},'!\" + \"]\", \"g\");\r\n const dashRegExp = new RegExp(\"[\" + \" |\\/\\\\_~()\" + \"]\", \"g\");\r\n let urlTitle = title.replace(removeRegExp, \"\");\r\n urlTitle = urlTitle.replace(dashRegExp, \"-\");\r\n urlTitle = urlTitle.replace(charRegExp, function (c: string): string {\r\n return (charReplaceTable.filter(cc => cc.key === c)[0] || { value: c }).value;\r\n });\r\n\r\n return urlTitle.replace(/[-]{2,}/g, \"-\").toLocaleLowerCase();\r\n },\r\n\r\n /**\r\n * Get the url path for views article or gallery\r\n * @param {ViewsUrlData} urlData Url details data\r\n * @returns {string} Url path extract from url data (ie: /en-us/news/good-news/the-title/ar-GBSD1B0?li=BB8GD11)\r\n */\r\n getViewsUrlPath(urlData: ViewsUrlData): string {\r\n let path: string = \"\";\r\n if (urlData && urlData.cmsId && urlData.title &&\r\n urlData.ns && urlData.vertical && urlData.locale) {\r\n\r\n let urlTitle = this.getFriendlyTitleForUrl(urlData.title);\r\n path = \"/\" + urlData.locale + \"/\" + urlData.vertical;\r\n\r\n if (urlData.sections && urlData.sections.length > 0) {\r\n path += \"/\" + urlData.sections.join(\"/\");\r\n }\r\n\r\n path += \"/\" + urlTitle + \"/\";\r\n path = path.toLocaleLowerCase() + urlData.ns + \"-\" + urlData.cmsId;\r\n\r\n if (urlData.query) {\r\n const q = urlData.query;\r\n path += (q && q[0] === \"?\") ? q : \"?\" + q;\r\n }\r\n }\r\n return path;\r\n },\r\n\r\n /**\r\n * Decode and strip html tags off markup\r\n * @param input Input markup text\r\n * @param replaceWith Optional text to replace html tags with\r\n */\r\n stripHtmlTags(input: string, replaceWith: string = \"\"): string {\r\n try {\r\n input = decodeURIComponent(input || \"\");\r\n } catch (error) {\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ViewsCommonAppErrors.InvalidDocumentContentError,\r\n message: \"Failed to strip HTML Tags. Content cannot be decoded.\",\r\n pb: {\r\n customMessage: `Failed to decode \"${input}\": ${error}.`\r\n }\r\n });\r\n }\r\n\r\n return input.replace(htmlTagsRegEx, replaceWith);\r\n },\r\n\r\n /**\r\n * Helper (mixin) for text truncation with (...) ellipses\r\n * @param numLines Number of line shown before truncation is applied.\r\n */\r\n applyTextTruncationStyles(numLines: number): any {\r\n return {\r\n display: \"-webkit-box\",\r\n \"text-overflow\": \"ellipsis\",\r\n \"-webkit-box-orient\": \"vertical\",\r\n \"-webkit-line-clamp\": numLines > 0 ? `${numLines}` : \"none\"\r\n };\r\n },\r\n\r\n /**\r\n * Detects if an HTML element is in the viewport\r\n */\r\n isInViewport(\r\n element: React.RefObject,\r\n inViewportPercentage: number,\r\n inViewportTopOffset: number = 0,\r\n inViewportBottomOffset: number = 0,\r\n allowZeroHeight: boolean = false\r\n ): boolean {\r\n const currentReference = element.current;\r\n\r\n if (currentReference) {\r\n const bounds = currentReference.getBoundingClientRect();\r\n\r\n const height = bounds.height;\r\n\r\n if (!allowZeroHeight && !height) {\r\n return false;\r\n }\r\n\r\n const top = bounds.top || 0;\r\n const bottom = bounds.bottom || 0;\r\n\r\n return (top + (height * (1 - inViewportPercentage)) - inViewportTopOffset >= 0 &&\r\n bottom - (height * (1 - inViewportPercentage)) + inViewportBottomOffset <= window.innerHeight);\r\n }\r\n\r\n return false;\r\n }\r\n};","module.exports = __webpack_public_path__ + \"AdChoices.svg\";","module.exports = __webpack_public_path__ + \"BingCardDefaultHotelImage.svg\";","module.exports = __webpack_public_path__ + \"BingHotelSeePrice.svg\";","module.exports = __webpack_public_path__ + \"BingLogo.svg\";","module.exports = __webpack_public_path__ + \"BingRatingDarkLightStar.svg\";","module.exports = __webpack_public_path__ + \"BingRatingDarkStar.svg\";","module.exports = __webpack_public_path__ + \"BingRatingLightStar.svg\";","module.exports = __webpack_public_path__ + \"BlowingHail.svg\";","module.exports = __webpack_public_path__ + \"BlowingHailWhite.svg\";","module.exports = __webpack_public_path__ + \"BlowingSnow.svg\";","module.exports = __webpack_public_path__ + \"BlowingSnowWhite.svg\";","module.exports = __webpack_public_path__ + \"Check.svg\";","module.exports = __webpack_public_path__ + \"Chevron.svg\";","module.exports = __webpack_public_path__ + \"CircleClose.svg\";","module.exports = __webpack_public_path__ + \"ClearNight.svg\";","module.exports = __webpack_public_path__ + \"ClearNightWhite.svg\";","module.exports = __webpack_public_path__ + \"Close.svg\";","module.exports = __webpack_public_path__ + \"Cloudy.svg\";","module.exports = __webpack_public_path__ + \"CloudyWhite.svg\";","module.exports = __webpack_public_path__ + \"Copy.svg\";","module.exports = __webpack_public_path__ + \"DarkModeHotel.svg\";","module.exports = __webpack_public_path__ + \"DayTime.svg\";","module.exports = __webpack_public_path__ + \"Delete.svg\";","module.exports = __webpack_public_path__ + \"Dislike.svg\";","module.exports = __webpack_public_path__ + \"DislikeText.svg\";","module.exports = __webpack_public_path__ + \"Disliked.svg\";","module.exports = __webpack_public_path__ + \"DislikedLight.svg\";","module.exports = __webpack_public_path__ + \"DislikedText.svg\";","module.exports = __webpack_public_path__ + \"Docx.svg\";","module.exports = __webpack_public_path__ + \"Download.svg\";","module.exports = __webpack_public_path__ + \"Edit.svg\";","module.exports = __webpack_public_path__ + \"Edited.svg\";","module.exports = __webpack_public_path__ + \"Ellipses.svg\";","module.exports = __webpack_public_path__ + \"EllipsesLight.svg\";","module.exports = __webpack_public_path__ + \"Excel.svg\";","module.exports = __webpack_public_path__ + \"Facebook.svg\";","module.exports = __webpack_public_path__ + \"FacebookText.svg\";","module.exports = __webpack_public_path__ + \"FacebookTextBlack.svg\";","module.exports = __webpack_public_path__ + \"Fog.svg\";","module.exports = __webpack_public_path__ + \"FogWhite.svg\";","module.exports = __webpack_public_path__ + \"Folder.svg\";","module.exports = __webpack_public_path__ + \"FolderOpen.svg\";","module.exports = __webpack_public_path__ + \"Form.svg\";","module.exports = __webpack_public_path__ + \"FreezingRain.svg\";","module.exports = __webpack_public_path__ + \"FreezingRainWhite.svg\";","module.exports = __webpack_public_path__ + \"GalleryFullscreen.svg\";","module.exports = __webpack_public_path__ + \"GalleryMediaIcon.svg\";","module.exports = __webpack_public_path__ + \"GenericFile.svg\";","module.exports = __webpack_public_path__ + \"GridView.svg\";","module.exports = __webpack_public_path__ + \"HailDay.svg\";","module.exports = __webpack_public_path__ + \"HailDayWhite.svg\";","module.exports = __webpack_public_path__ + \"HailNight.svg\";","module.exports = __webpack_public_path__ + \"HailNightWhite.svg\";","module.exports = __webpack_public_path__ + \"HazeSmoke.svg\";","module.exports = __webpack_public_path__ + \"HazeSmokeWhite.svg\";","module.exports = __webpack_public_path__ + \"HeavySnow.svg\";","module.exports = __webpack_public_path__ + \"HeavySnowWhite.svg\";","module.exports = __webpack_public_path__ + \"Hide.svg\";","module.exports = __webpack_public_path__ + \"HideStory.svg\";","module.exports = __webpack_public_path__ + \"Hotel.svg\";","module.exports = __webpack_public_path__ + \"Information.svg\";","module.exports = __webpack_public_path__ + \"InteractionRequiredDark.svg\";","module.exports = __webpack_public_path__ + \"InteractionRequiredLight.svg\";","module.exports = __webpack_public_path__ + \"Interested.svg\";","module.exports = __webpack_public_path__ + \"LightRain.svg\";","module.exports = __webpack_public_path__ + \"LightRainWhite.svg\";","module.exports = __webpack_public_path__ + \"LightSnow.svg\";","module.exports = __webpack_public_path__ + \"LightSnowWhite.svg\";","module.exports = __webpack_public_path__ + \"Like.svg\";","module.exports = __webpack_public_path__ + \"LikeText.svg\";","module.exports = __webpack_public_path__ + \"Liked.svg\";","module.exports = __webpack_public_path__ + \"LikedText.svg\";","module.exports = __webpack_public_path__ + \"Line.svg\";","module.exports = __webpack_public_path__ + \"LinkedIn.svg\";","module.exports = __webpack_public_path__ + \"LinkedInBlack.svg\";","module.exports = __webpack_public_path__ + \"LinkedInText.svg\";","module.exports = __webpack_public_path__ + \"Mail.svg\";","module.exports = __webpack_public_path__ + \"MailBlack.svg\";","module.exports = __webpack_public_path__ + \"ManagedBriefcase.svg\";","module.exports = __webpack_public_path__ + \"Message.svg\";","module.exports = __webpack_public_path__ + \"Messages.svg\";","module.exports = __webpack_public_path__ + \"MicrosoftNews.svg\";","module.exports = __webpack_public_path__ + \"MicrosoftNewsFull.svg\";","module.exports = __webpack_public_path__ + \"MicrosoftNewsFull_FR.svg\";","module.exports = __webpack_public_path__ + \"MicrosoftNewsFull_ZH.svg\";","module.exports = __webpack_public_path__ + \"ModerateRain.svg\";","module.exports = __webpack_public_path__ + \"ModerateRainWhite.svg\";","module.exports = __webpack_public_path__ + \"Movie.svg\";","module.exports = __webpack_public_path__ + \"NightTime.svg\";","module.exports = __webpack_public_path__ + \"OfficeFormsLogo.svg\";","module.exports = __webpack_public_path__ + \"OneDrive.svg\";","module.exports = __webpack_public_path__ + \"OneNote.svg\";","module.exports = __webpack_public_path__ + \"Onetoc.svg\";","module.exports = __webpack_public_path__ + \"Outlook.svg\";","module.exports = __webpack_public_path__ + \"PartlyCloudyDay.svg\";","module.exports = __webpack_public_path__ + \"PartlyCloudyDayWhite.svg\";","module.exports = __webpack_public_path__ + \"PartlyCloudyNight.svg\";","module.exports = __webpack_public_path__ + \"PartlyCloudyNightWhite.svg\";","module.exports = __webpack_public_path__ + \"Pdf.svg\";","module.exports = __webpack_public_path__ + \"People.svg\";","module.exports = __webpack_public_path__ + \"Pin.svg\";","module.exports = __webpack_public_path__ + \"PowerPoint.svg\";","module.exports = __webpack_public_path__ + \"Pptx.svg\";","module.exports = __webpack_public_path__ + \"RainShowersDay.svg\";","module.exports = __webpack_public_path__ + \"RainShowersDayWhite.svg\";","module.exports = __webpack_public_path__ + \"RainShowersNight.svg\";","module.exports = __webpack_public_path__ + \"RainShowersNightWhite.svg\";","module.exports = __webpack_public_path__ + \"RainSnow.svg\";","module.exports = __webpack_public_path__ + \"RainSnowShowersDay.svg\";","module.exports = __webpack_public_path__ + \"RainSnowShowersDayWhite.svg\";","module.exports = __webpack_public_path__ + \"RainSnowShowersNight.svg\";","module.exports = __webpack_public_path__ + \"RainSnowShowersNightWhite.svg\";","module.exports = __webpack_public_path__ + \"RainSnowWhite.svg\";","module.exports = __webpack_public_path__ + \"Refresh.svg\";","module.exports = __webpack_public_path__ + \"Remove.svg\";","module.exports = __webpack_public_path__ + \"Save.svg\";","module.exports = __webpack_public_path__ + \"Saved.svg\";","module.exports = __webpack_public_path__ + \"Search.svg\";","module.exports = __webpack_public_path__ + \"Share.svg\";","module.exports = __webpack_public_path__ + \"ShareLight.svg\";","module.exports = __webpack_public_path__ + \"Sharepoint.svg\";","module.exports = __webpack_public_path__ + \"Skype.svg\";","module.exports = __webpack_public_path__ + \"SkypeOffice.svg\";","module.exports = __webpack_public_path__ + \"SnowShowersDay.svg\";","module.exports = __webpack_public_path__ + \"SnowShowersDayWhite.svg\";","module.exports = __webpack_public_path__ + \"SnowShowersNight.svg\";","module.exports = __webpack_public_path__ + \"SnowShowersNightWhite.svg\";","module.exports = __webpack_public_path__ + \"SunnyDay.svg\";","module.exports = __webpack_public_path__ + \"SunnyDayWhite.svg\";","module.exports = __webpack_public_path__ + \"Sway.svg\";","module.exports = __webpack_public_path__ + \"SwayApp.svg\";","module.exports = __webpack_public_path__ + \"Teams.svg\";","module.exports = __webpack_public_path__ + \"ThumbnailView.svg\";","module.exports = __webpack_public_path__ + \"Thunderstorms.svg\";","module.exports = __webpack_public_path__ + \"ThunderstormsWhite.svg\";","module.exports = __webpack_public_path__ + \"Trending.svg\";","module.exports = __webpack_public_path__ + \"Twitter.svg\";","module.exports = __webpack_public_path__ + \"TwitterBlack.svg\";","module.exports = __webpack_public_path__ + \"TwitterText.svg\";","module.exports = __webpack_public_path__ + \"Unpin.svg\";","module.exports = __webpack_public_path__ + \"Upload.svg\";","module.exports = __webpack_public_path__ + \"VerticalSeparator.svg\";","module.exports = __webpack_public_path__ + \"VideoMediaIcon.svg\";","module.exports = __webpack_public_path__ + \"VideoPlay.svg\";","module.exports = __webpack_public_path__ + \"Visio.svg\";","module.exports = __webpack_public_path__ + \"Vsdx.svg\";","module.exports = __webpack_public_path__ + \"WeatherAlert.svg\";","module.exports = __webpack_public_path__ + \"WhatsApp.svg\";","module.exports = __webpack_public_path__ + \"WhatsAppBlack.svg\";","module.exports = __webpack_public_path__ + \"Windy.svg\";","module.exports = __webpack_public_path__ + \"WindyWhite.svg\";","module.exports = __webpack_public_path__ + \"Word.svg\";","module.exports = __webpack_public_path__ + \"World.svg\";","module.exports = __webpack_public_path__ + \"Xlsx.svg\";","module.exports = __webpack_public_path__ + \"Yammer.svg\";","// © Microsoft Corporation. All rights reserved.\r\n\r\nexport enum TelemetryTypes {\r\n Undefined = 0,\r\n Header = 1,\r\n Footer = 2,\r\n TopNavBar = 3,\r\n NavBar = 4,\r\n DropDown = 5,\r\n Section = 6,\r\n Carousel = 7,\r\n Module = 8,\r\n SearchBox = 9,\r\n InputBox = 10,\r\n ActionButton = 11,\r\n Interaction = 12,\r\n Headline = 13,\r\n Navigation = 14,\r\n Entity = 15,\r\n StructuredData = 16,\r\n AppStore = 17,\r\n AppLaunch = 18,\r\n CmsPromotions = 19,\r\n MicrosoftWebStore = 20,\r\n XboxStore = 21,\r\n OfficeStore = 22,\r\n AppInstall = 23,\r\n PartnerLinks = 24,\r\n SponsoredContent = 25,\r\n Follow = 26,\r\n Unfollow = 27,\r\n MoreFrom = 28,\r\n Topic = 29,\r\n Provider = 30,\r\n Spotlight = 33,\r\n Close = 36,\r\n Share = 37,\r\n Like = 38,\r\n Dislike = 39,\r\n Unlike = 40,\r\n Undislike = 41,\r\n Mute = 42,\r\n Unmute = 43,\r\n MuteCancel = 44,\r\n Manage = 45,\r\n NewStories = 46,\r\n AutoSuggest = 47,\r\n BingCard = 48,\r\n Tile = 49,\r\n TrendingNews = 50,\r\n AllCoverage= 51,\r\n Report = 52,\r\n AdChoice = 53,\r\n MsccCookieComplianceBanner = 54,\r\n Hide = 55,\r\n Unhide = 56,\r\n CookieWallCookieComplianceBanner = 57\r\n}\r\n\r\nexport enum ContentTypes {\r\n StructuredData = 8\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n// See https://webpack.js.org/guides/public-path/#on-the-fly for the details of __webpack_public_path__\r\n\r\ndeclare var __webpack_public_path__: string;\r\nconst prodAssets = \"//assets.msn.com\";\r\nconst cnProdAssets = \"//assets.msn.cn\";\r\n\r\nconst ENV = {\r\n \"microsoftnews.msn.com\": prodAssets,\r\n \"microsoftnews-int1.msn.com\": prodAssets,\r\n \"microsoftnews.msn.cn\": cnProdAssets,\r\n \"microsoftnews-int1.msn.cn\": cnProdAssets,\r\n \"microsoftnews-dev.msn.com\": prodAssets,\r\n \"ntp.msn.com\": prodAssets,\r\n \"ntp.msn.cn\": cnProdAssets,\r\n \"www.msn.com\": prodAssets,\r\n \"int1.msn.com\": prodAssets,\r\n \"int1.msn.cn\": cnProdAssets,\r\n \"int.msn.com\": prodAssets,\r\n \"int.msn.cn\": cnProdAssets,\r\n \"pagecomposition.msn.com\": prodAssets,\r\n \"pagecomposition-int.msn.com\": prodAssets,\r\n \"localhost:6000\": prodAssets // for pcs local dev box\r\n};\r\n\r\nexport const initializePublicPath = () => {\r\n if (ENV[window.location.host]) {\r\n const search = decodeURIComponent(window.location.search);\r\n const isOverriden = search.indexOf(\"item=spalink:\") > -1;\r\n const isRolling = isOverriden && search.indexOf(\"item=spalink:rolling\") > -1;\r\n\r\n if (isOverriden && !isRolling) {\r\n __webpack_public_path__ = ENV[window.location.host] + __webpack_public_path__;\r\n } else {\r\n // default case without spalink override\r\n // in order to have the lazy chunk pointing to latest with a stable path, the build number will be overridden on runtime\r\n // PATHNAME: /bundles/v1/mmx/20190221.2/\r\n // PATHNAME.split(\"/\"): [\"\", \"bundles\", \"v1\", \"mmx\", \"20190221.2\", \"\"]\r\n const segments = __webpack_public_path__.split(\"/\");\r\n segments[4] = isRolling ? \"rolling\" : \"latest\";\r\n __webpack_public_path__ = ENV[window.location.host] + segments.join(\"/\");\r\n }\r\n }\r\n};\r\n\r\nexport const initializeHybridPublicPath = () => {\r\n const search = decodeURIComponent(window.location.search);\r\n if (search.indexOf(\"item=spa_env:localdev\") > -1) {\r\n // Use active prime instance SPA directory for localdev\r\n __webpack_public_path__ = `//${window.location.host}/spa/`;\r\n return;\r\n }\r\n\r\n const host = ENV[window.location.host] || prodAssets;\r\n const isOverriden = search.indexOf(\"item=spalink:\") > -1;\r\n if (isOverriden) {\r\n __webpack_public_path__ = host + __webpack_public_path__;\r\n } else {\r\n // default case without spalink override\r\n // in order to have the lazy chunk pointing to latest with a stable path, the build number will be overridden on runtime\r\n // PATHNAME: /bundles/v1/mmx/20190221.2/\r\n // PATHNAME.split(\"/\"): [\"\", \"bundles\", \"v1\", \"mmx\", \"20190221.2\", \"\"]\r\n const segments = __webpack_public_path__.split(\"/\");\r\n segments[4] = \"latest\";\r\n __webpack_public_path__ = host + segments.join(\"/\");\r\n }\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { initializeHybridPublicPath } from \"@msnews/core\";\r\n\r\ninitializeHybridPublicPath();","// © Microsoft Corporation. All rights reserved.\r\n\r\nexport enum ExperienceState {\r\n /**\r\n * State when experience has not started its lifecycle events\r\n */\r\n NotStarted = 0,\r\n\r\n /**\r\n * This state is when experience is waiting to load its bundles\r\n */\r\n WaitingToLoad = 1,\r\n\r\n /**\r\n * Bundles loaded for experience and connector has been initialized\r\n */\r\n LoadedWaitingToRender = 2,\r\n\r\n /**\r\n * All milestone dependencies have been resolved for this experience and its ready to render\r\n */\r\n ReadyToRender = 3,\r\n\r\n /**\r\n * Experience failed to load\r\n */\r\n Failed = 4,\r\n\r\n /**\r\n * Experience state is not known, probably when timeout happened before dependency is resolved or dependency is on some UI event.\r\n */\r\n Unknown = 5\r\n}","\r\n// © Microsoft Corporation. All rights reserved.\r\n\r\nexport enum ChildExperiencesDeferRenderType {\r\n /**\r\n * Wait for all child experinces milestone load dependecies to be resolved, once all child experiences are loaded and available\r\n * triggers parent re-render. Best from perfomance standpoint as it does a single re-render of parent\r\n */\r\n batch = \"batch\",\r\n\r\n /**\r\n * Render every child experince as soon as its available after milestone load dependecies has been resolved, This is less performant as it triggers\r\n * parent re-render multiple times for each delay loaded child experience\r\n */\r\n renderWhenAvailable = \"renderWhenAvailable\"\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ActionMap } from \"../reducers\";\r\nimport { ConnectorConstants } from \"../constants/ConnectorConstants\";\r\nimport { ConnectorNamespaces } from \"@msnews/experiences-constants\";\r\n\r\n/**\r\n * Action signature to trigger an experience to render\r\n */\r\ntype RenderExperienceSignature = () => void;\r\n\r\n/**\r\n * Action signature to initialize data connector state merge.\r\n */\r\ntype DataConnectorMergeInitSignature = (dataConnectorName: ConnectorNamespaces) => void;\r\n\r\n/**\r\n * Actions that are common to all experiences\r\n * @class\r\n */\r\nexport class CommonActions {\r\n /**\r\n * Definition for an action that can be dispatched to any experience causing it to render\r\n */\r\n public static renderExperience: ActionMap = new ActionMap(ConnectorConstants.renderAction);\r\n\r\n /**\r\n * Definition for an action that initializes shared data connector state on an experience.\r\n */\r\n public static dataConnectorMergeInit: ActionMap = new ActionMap(ConnectorConstants.dataConnectorMergeInitAction);\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ChildExperienceConfigInfo } from \"./ChildExperienceConfigInfo\";\r\n\r\n/**\r\n * Specifies validator for child experience\r\n * @export\r\n * @interface\r\n */\r\nexport interface ChildExperienceValidator {\r\n /**\r\n * section name from where child element should be removed\r\n */\r\n sectionName: ValidatorSectionName;\r\n\r\n /**\r\n * ChildExperienceConfigInfo object to be removed\r\n */\r\n childExperienceConfigInfo: ChildExperienceConfigInfo;\r\n}\r\n\r\n/**\r\n * section name from where child element should be removed. We can add more support in this list as additionalChildExperiences\r\n * or childExperienceMap. The current design and approach support that.\r\n */\r\nexport enum ValidatorSectionName {\r\n /**\r\n * Section name for River Grid children, positioned by row/column syntax\r\n */\r\n riverGridChildren = \"riverGridChildren\"\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { BaseExperienceConfig, ChildExperienceValidator, ValidatorSectionName } from \"@msnews/core\";\r\nimport { AppValidator } from \"./AppValidator\";\r\n\r\n/**\r\n * Config Processor class to filter config\r\n * @class\r\n */\r\nexport class ConfigProcessor {\r\n /**\r\n * experience validator map to be provided by app type. Each entry has a validator name and a validator function associated \r\n * with that.\r\n */\r\n static expValidatorMap: Map boolean> = new Map();\r\n\r\n /**\r\n * Registers apptype validators\r\n * @method\r\n * @param {AppValidator} apptypeValidator Validator for a specific app type\r\n * @returns {void}\r\n */\r\n public static registerAppValidator(apptypeValidator: AppValidator): void {\r\n this.expValidatorMap = apptypeValidator.getAllValidators();\r\n }\r\n\r\n /**\r\n * process config based on registered validators for current app-type and removes child experience from \r\n * section defined in CMS condig\r\n * @method\r\n * @param {BaseExperienceConfig} expConfig Experience config object\r\n * @returns {BaseExperienceConfig} returns filtered experience config\r\n */\r\n public static processConfig(expConfig: BaseExperienceConfig): BaseExperienceConfig {\r\n if (!this.expValidatorMap || this.expValidatorMap.size < 1 || !expConfig || !expConfig.childExpValidatorMap) {\r\n return expConfig;\r\n }\r\n\r\n const expMap: { [instanceId: string]: ChildExperienceValidator } = expConfig.childExpValidatorMap;\r\n\r\n for (const validatorName in expMap) {\r\n var childExpValidator = expMap[validatorName];\r\n if (this.expValidatorMap.has(validatorName)) {\r\n const validator = this.expValidatorMap.get(validatorName);\r\n const removeChildExp = validator();\r\n if (removeChildExp) {\r\n expConfig = this.filterConfig(childExpValidator, expConfig);\r\n }\r\n\r\n }\r\n }\r\n\r\n return expConfig;\r\n }\r\n\r\n /**\r\n * remove child experience based on the response from registerd validator and config.\r\n * @method\r\n * @param {ChildExperienceValidator} childExpValidator Experience config object\r\n * @param {BaseExperienceConfig} expConfig Experience config object\r\n * @returns {BaseExperienceConfig} returns filtered experience config\r\n */\r\n private static removeFromRiverGridChildren(childExpValidator: ChildExperienceValidator, expConfig: any): BaseExperienceConfig {\r\n // TODO: River config is in experiences and we should not take dependency of experiences in this project.\r\n // We should move RiverConfig to core config project or expConfig has to be of type any\r\n let riverGridChildren = expConfig.riverGridChildren;\r\n if (riverGridChildren) {\r\n riverGridChildren.forEach(element => {\r\n let childElems = element.children;\r\n if (childElems) {\r\n element.children = childElems.filter((childExp) => {\r\n const configInfo = childExp.childExperienceConfigInfo;\r\n return !configInfo || !childExpValidator.childExperienceConfigInfo\r\n || childExpValidator.childExperienceConfigInfo.instanceId !== configInfo.instanceId\r\n || childExpValidator.childExperienceConfigInfo.experienceType !== configInfo.experienceType;\r\n });\r\n }\r\n });\r\n }\r\n\r\n return expConfig;\r\n }\r\n\r\n /**\r\n * Verify if the section provided in CMS schema is supported for removal of child experiences.\r\n * Currently only riverGridChildren is supported. Support will be extended to other sections.\r\n * @method\r\n * @param {ChildExperienceValidator} childExpValidator Experience config object\r\n * @param {BaseExperienceConfig} expConfig Experience config object\r\n * @returns {BaseExperienceConfig} returns filtered experience config\r\n */\r\n private static filterConfig(childExpValidator: ChildExperienceValidator, expConfig: BaseExperienceConfig): BaseExperienceConfig {\r\n if (childExpValidator && typeof childExpValidator.sectionName === \"string\" && childExpValidator.sectionName.toLowerCase() === ValidatorSectionName.riverGridChildren.toLowerCase()) {\r\n return this.removeFromRiverGridChildren(childExpValidator, expConfig);\r\n }\r\n\r\n return expConfig;\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n DynamicBundles,\r\n ExperienceConfigWrapper,\r\n TelemetryBase,\r\n resolver\r\n} from \"@msnews/core\";\r\nimport { ExperienceLoadingState, MilestoneDataActions, getMilestoneDataConnector } from \"@msnews/milestone-data\";\r\nimport { tryGetPerfTimeline, renamePerfTimeline } from \"@msnews/diagnostics\";\r\n\r\nimport { ChildExperienceConfigInfo } from \"@msnews/core\";\r\nimport { ExperienceLoaderAppErrors } from \"@msnews/diagnostics\";\r\nimport { IComponentConnector } from \"../\";\r\nimport { PageBase } from \"@msnews/experiences-redux\";\r\nimport React from \"react\";\r\nimport { Store } from \"react-redux\";\r\nimport { uniqueId } from \"lodash-es\";\r\n\r\n/**\r\n * An experience loader class that encapsulates the dynamic loading of an experience.\r\n * Give an experience config href, this class will determine the bundle to be loaded, load the bundle, and then enable the caller to get\r\n * the connected render component for the experience.\r\n * The loading/initialization of the experience connector and the connecting are separate methods, so that the caller can control when each is done\r\n */\r\nexport class ExperienceLoader {\r\n /**\r\n * The connector for this instance of the experience loader. It is undefined until after loadConnector is called\r\n */\r\n private experienceConnector: IComponentConnector = undefined;\r\n\r\n /**\r\n * The experience rendering Component for this instance of the experience loader. It is undefined until after loadConnector is called\r\n */\r\n private experienceComponent: any = undefined;\r\n\r\n /**\r\n * The experience Type of the experience being loaded. It is undefined until after loadConnector is called\r\n */\r\n private $experienceType: string = undefined;\r\n\r\n /**\r\n * Gets the experience Type for this instance of the experience loader. It is undefined until after loadConnector is called\r\n */\r\n public get experienceType(): string { return this.$experienceType; }\r\n\r\n /**\r\n * Gets the current Connector for this experience loader instance\r\n */\r\n public get connector(): IComponentConnector { return this.experienceConnector; }\r\n\r\n /**\r\n * Creates an experience loader.\r\n * @param {string} configIndexHref The config index href for the config to load (ex: cms/api/amp/experienceConfigIndex/BBTjjqH ).\r\n * @param {string} [instanceId] The instanceId of the experience\r\n * @param {string} [parentNamespace] The namespace of the parent experience, if it is known\r\n * @param {Store} [parentStore] The parent experience redux store\r\n * @param {string} [type] The experienceType of the experience being loaded. If provided, this type will be used to load the bundle\r\n */\r\n public constructor(\r\n private configIndexHref: string,\r\n private instanceId?: string | undefined,\r\n private parentNamespace?: string | undefined,\r\n private parentStore?: Store | undefined,\r\n experienceType?: string | undefined) {\r\n\r\n this.$experienceType = experienceType;\r\n }\r\n\r\n /**\r\n * Dynamically loads and experience bundle, and creates the experience connector\r\n */\r\n public async loadConnector(isDataConnector: boolean = false): Promise {\r\n\r\n // Log an app error, if we didn't get either a configIndexHref NOR an experienceType\r\n if (!this.configIndexHref && !this.$experienceType) {\r\n // Log an app error if the loader failed to load for whatever reason\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ExperienceLoaderAppErrors.InsufficientLoadArgs,\r\n message: `Failed loading experience bundle due to missing config href and experienceType. Details: ` + JSON.stringify({ instanceId: this.instanceId, parentNamespace: this.parentNamespace })\r\n });\r\n throw new Error(\"Cannot load a connector bundle without either the experienceType, or configIndexHref\");\r\n }\r\n\r\n const perfTimeline = tryGetPerfTimeline(this.$experienceType || uniqueId(), this.instanceId);\r\n\r\n // the loaded config result\r\n let configResult: ExperienceConfigWrapper;\r\n\r\n // Get a promise for the resolved config of the experience that is being initialized. If not configIndexHref is supplied,\r\n // then assume the experience has no config, so just create a resolved promise the returns an empty config\r\n const configPromise = this.configIndexHref\r\n ? perfTimeline\r\n ? perfTimeline.instrumentPromise(\"config\", () => resolver.getConfig(this.configIndexHref))\r\n : resolver.getConfig(this.configIndexHref)\r\n : Promise.resolve({ experienceType: this.$experienceType, properties: {} });\r\n\r\n // The async promises for loading the config and loading the bundles\r\n const loaderPromises: Promise[] = [configPromise];\r\n\r\n // If we don't know the experienceType, then we need to wait for the config to load and get it from the child config\r\n if (!this.$experienceType) {\r\n configResult = await configPromise;\r\n this.$experienceType = configResult.experienceType;\r\n\r\n // if we didn't have $experienceType at construction time, then we would've used uniqueId() to create this\r\n // temporary timeline. Now that we have the proper type, rename the timeline to the known value.\r\n if (perfTimeline) {\r\n renamePerfTimeline(perfTimeline, this.$experienceType);\r\n }\r\n }\r\n\r\n // Get a promise for loading in the experience bundle\r\n const bundlePromise = perfTimeline\r\n ? perfTimeline.instrumentPromise(\"scripts\", () => DynamicBundles.loadExperience(this.$experienceType))\r\n : DynamicBundles.loadExperience(this.$experienceType);\r\n\r\n loaderPromises.push(bundlePromise);\r\n\r\n // Wait for all of the promises to complete. This will either be both the config and bundle promises,\r\n // or the bundle promise with the pre-resolved config promise to the empty config object.\r\n await Promise.all(loaderPromises);\r\n\r\n // If we don't have the config result yet, get it from the completed promises.\r\n if (!configResult) {\r\n configResult = await configPromise;\r\n }\r\n\r\n // Get the bundle from the completed promises\r\n const bundleModule = await bundlePromise;\r\n\r\n const initMeasureEnd = perfTimeline && perfTimeline.startMeasure(\"init\").endMeasure;\r\n\r\n // update experience current state to loaded\r\n this.updateExperienceLoadedMilestone(this.$experienceType);\r\n\r\n // Extract config object from result\r\n const config = configResult.properties;\r\n\r\n // Get the Connector/Reducer/Component via naming convention\r\n const ExperienceConnector = bundleModule[this.$experienceType + \"Connector\"];\r\n const ExperienceReducer = bundleModule[this.$experienceType + \"Reducer\"];\r\n\r\n // Store the experience rendering component as a class member, for use later when it is connected\r\n this.experienceComponent = bundleModule[this.$experienceType];\r\n\r\n // Create the experience connector. The namespace is a combination of the experienceType and its instance ID (in case there are multiple of them on a page)\r\n const app = PageBase.getInstance();\r\n let experienceNamespace = getExperienceNamespace({ experienceType: this.$experienceType, instanceId: this.instanceId, href: this.configIndexHref });\r\n\r\n let experienceParentNamespace = this.parentNamespace ? this.parentNamespace : \"\";\r\n let experienceStore = this.parentStore ? this.parentStore : app.store;\r\n\r\n // Data connectors are singletons, and so their registered namespace is only their experienceType. This allows\r\n // data connectors to be found by using the constants in the ExperienceIds enum\r\n this.experienceConnector = new ExperienceConnector(\r\n isDataConnector ? this.$experienceType : experienceNamespace,\r\n experienceParentNamespace,\r\n app.rootReducer,\r\n new ExperienceReducer(config),\r\n experienceStore,\r\n config\r\n );\r\n\r\n // Set the experience config index href property on the connector.\r\n this.experienceConnector.configHref = this.configIndexHref;\r\n\r\n if (initMeasureEnd) {\r\n initMeasureEnd();\r\n }\r\n }\r\n\r\n /**\r\n * Creates and returns the connected rendering component for the experience\r\n * @param connectorProps Any initial props that should be passed to the connector in its onComponentConnect() method\r\n * @returns The Connected component for the experience\r\n */\r\n public async getConnectedExperience(connectorProps?: any): Promise {\r\n // If the connector has not been loaded yet, then load it first\r\n if (!this.experienceConnector) {\r\n await this.loadConnector();\r\n }\r\n\r\n // Return a promise that will resolve to the connected component, ready to render.\r\n return this.experienceConnector.connectComponent(this.experienceComponent, connectorProps);\r\n }\r\n\r\n /**\r\n * update loaded milestone for the experience\r\n * @param experienceType - Experience Type to update\r\n */\r\n private updateExperienceLoadedMilestone(experienceType: string): void {\r\n let milestoneDataConnector = getMilestoneDataConnector();\r\n if (milestoneDataConnector) {\r\n MilestoneDataActions.updateExperienceCurrentState.getActionSender(milestoneDataConnector)\r\n .send(experienceType, ExperienceLoadingState.loaded, null, null);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Creates a namespace based on the passed in experience config info\r\n * @param experienceConfigInfo\r\n */\r\nexport function getExperienceNamespace(experienceConfigInfo: ChildExperienceConfigInfo): string {\r\n return `${experienceConfigInfo.experienceType}_${experienceConfigInfo.href}_${experienceConfigInfo.instanceId}`;\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n AppError,\r\n ColumnArrangement,\r\n ExperienceInitialPositionProps,\r\n ExperienceInitialProps,\r\n Telemetry,\r\n TelemetryProps,\r\n TelemetryTags,\r\n TelemetryTypes,\r\n fastBreakpointManager\r\n} from \"@msnews/experiences-base\";\r\nimport {\r\n BaseExperienceConfig,\r\n ChildArrangementMetadata,\r\n ChildExperienceConfigInfo,\r\n ChildExperiencesDeferRenderType,\r\n ChildInfo,\r\n ChildrenTypes,\r\n CustomCompositionConfig,\r\n ExperienceCompositionTypes,\r\n ExperienceState,\r\n GridCompositionConfig,\r\n LayoutConfig,\r\n PeregrineChildInfo,\r\n ScreenTypeMetadata,\r\n ScreenWidth,\r\n TelemetryBase,\r\n appEnvironment,\r\n resolver\r\n} from \"@msnews/core\";\r\nimport {\r\n CommonActions,\r\n DataConnector,\r\n DynamicReducer,\r\n IActionPayload,\r\n IReducer,\r\n PageBase,\r\n dataConnectorInjector\r\n} from \"@msnews/experiences-redux\";\r\nimport { ComponentConnectorAppErrors, logger } from \"@msnews/diagnostics\";\r\nimport { DeferralEventType, ExperienceMilestoneEventTypes, MilestoneDataActions, MilestoneDataConnector, getExperienceLoadDelegate, getExperienceRenderDelegate } from \"@msnews/milestone-data\";\r\nimport { Dispatch, Store } from \"redux\";\r\n\r\nimport { ConfigProcessor } from \"@msnews/config-validator\";\r\nimport { ConnectorNamespaces } from \"@msnews/experiences-constants\";\r\nimport { ExperienceLoadInfo } from \"./ExperienceLoadInfo\";\r\nimport { ExperienceLoader } from \"..\";\r\nimport { IComponentConnector } from \"./IComponentConnector\";\r\nimport React from \"react\";\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\nimport { connect } from \"react-redux\";\r\nimport { getMilestoneDataConnector } from \"@msnews/milestone-data\";\r\nimport { instrumentPerf } from \"./ExperiencePerfTimeline\";\r\nimport { isEmpty } from \"lodash-es\";\r\nimport { isFunction } from \"util\";\r\nimport { subspaced } from \"react-redux-subspace\";\r\n\r\nexport type mapToPropsSignature = (state: TState, ownProps?: TProps) => TProps;\r\nexport type mapStateToPropsReturnType = TProps | mapToPropsSignature;\r\nexport type mapDispatchToPropsReturnType = TProps | mapToPropsSignature;\r\n\r\n\r\n/**\r\n * Map for making config-less data connectors faster to load\r\n *\r\n * HACK: HACK: HACK: This is a temporary hack until we can update CMS configs to remove\r\n * the HREF requirement for config-less connectors, so that we can opt out\r\n * of loading configs without having this special check. Need to do in phases\r\n * so that we're not breaking PROD users with old scripts.\r\n */\r\nexport const ConfiglessConnectors = {\r\n [ConnectorNamespaces.BingImageData]: true,\r\n [ConnectorNamespaces.OneServiceContent]: true,\r\n [ConnectorNamespaces.Telemetry]: true,\r\n [ConnectorNamespaces.TopicData]: true,\r\n [ConnectorNamespaces.PageClickTrackerData]: true\r\n};\r\n\r\n/**\r\n * Base class for a component connector. Every connected component in an app has a connector that inherits from this class\r\n * @class\r\n */\r\nexport abstract class ComponentConnector\r\n extends DataConnector\r\n implements IComponentConnector {\r\n\r\n /**\r\n * A map of child connectors. The key to the map is a concatenation: ExperienceType_ExperienceInstanceId.\r\n * The ExperienceType is the the same as the ExperienceId in the @msnews/experiences-constants ExperienceIds enum (i.e. River)\r\n * The ExperienceInstanceId is set in config, as part of the parent experience config. Which children get created and rendered\r\n * by a parent experience will be specific to that experience, so it will be up to the parent experience to determine the\r\n * instanceId of the children to be rendered by looking in its config object.\r\n * @type Map>\r\n */\r\n protected childMap?: Map> = new Map();\r\n\r\n /**\r\n * This experiences telemetry props, derived from the parent telemetry props\r\n */\r\n protected telemetryProps: TelemetryProps = {};\r\n\r\n /**\r\n * The telemetry tags to pass along as unhandled props for rendering\r\n */\r\n protected telemetryTags: TelemetryTags = {};\r\n\r\n /**\r\n * The group the experience belongs to, if applicable. This property is to be set as needed in the specific experience connectors\r\n */\r\n protected $experienceGroup: string = undefined;\r\n\r\n /**\r\n * The connected rendering component for the experience connector\r\n */\r\n private $connectedComponent: React.ComponentClass = undefined;\r\n\r\n /**\r\n * The connected rendering component ReactElement instance for the experience connector\r\n */\r\n private $componentInstance: React.ReactElement = undefined;\r\n\r\n /**\r\n * The connector props used to connector this connector to an experience\r\n */\r\n private $connectorProps: ExperienceInitialProps;\r\n\r\n /**\r\n * flag indicating if we should render when offline. Default is false\r\n */\r\n private $renderIfOffline: boolean = false;\r\n\r\n /**\r\n * The experience type\r\n */\r\n private $experienceType: string = undefined;\r\n\r\n /**\r\n * failsafe timeout(ms) to render child experiences based on milestone batch load strategy\r\n */\r\n private $maxWaitToBatchRenderChildExperiences: number = 4000;\r\n\r\n /**\r\n * The milestone data connector (if it exists)\r\n */\r\n private $milestoneDataConnector: MilestoneDataConnector = undefined;\r\n\r\n /**\r\n * Gets the connected component for this experience\r\n */\r\n public get connectedComponent(): React.ComponentClass { return this.$connectedComponent; }\r\n\r\n /**\r\n * Gets the component instance for this experience. This is used for rendering the experience\r\n */\r\n public get componentInstance(): React.ReactElement { return this.$componentInstance; }\r\n\r\n /**\r\n * Gets the experience type for this experience.\r\n */\r\n public get experienceType(): string { return this.$experienceType; }\r\n\r\n /**\r\n * Sets the component instance for this experience\r\n */\r\n public set componentInstance(value: React.ReactElement) { this.$componentInstance = value; }\r\n\r\n /**\r\n * Sets the renderIfOffline flag\r\n */\r\n public set renderIfOffline(value: boolean) { this.$renderIfOffline = value; }\r\n\r\n /**\r\n * Get a map of the child experience component instances, which is appropriate for passing into the\r\n * inspector function as part of mapStateToProps\r\n */\r\n public get childComponentInstanceList(): { [instanceId: string]: React.ReactElement; } {\r\n const childComponentList: { [instanceId: string]: React.ReactElement; } = {};\r\n this.childMap.forEach((connector, key) => {\r\n childComponentList[key] = connector.componentInstance;\r\n });\r\n return childComponentList;\r\n }\r\n\r\n /**\r\n * Construct a new Component connector\r\n * @constructor\r\n * @param { string } namespace The redux subspace namespace for the connector\r\n * @param { string } parentNamespace The redux subspace namespace for the parent connector, if it exists\r\n * @param { DynamicReducer } rootReducer The root reducer for the Application\r\n * @param { IReducer } reducer The reducer for this connector instance\r\n * @param { Store} parentStore The parent store (or redux subspace) that this connector will be a subspace within\r\n * @param { TConfig } config Optional param containing the config for the connector\r\n */\r\n public constructor(namespace: string,\r\n parentNamespace: string,\r\n rootReducer: DynamicReducer,\r\n reducer: IReducer,\r\n parentStore: Store,\r\n config?: TConfig\r\n ) {\r\n super(namespace, parentNamespace, rootReducer, reducer, parentStore, config);\r\n this.selectComponentState = this.selectComponentState.bind(this);\r\n\r\n // To get the experience type, split the namespace at the first \"_\" and use the first substring\r\n // as the type. The convention for namespace is: ExperienceType_configHref_InstanceId. If there is no instanceId, then then namespace is just: ExperienceType\r\n this.$experienceType = namespace.split(\"_\")[0];\r\n\r\n ConfigProcessor.processConfig(this.config);\r\n }\r\n\r\n /**\r\n * Redux mapper used to map the current state to props the component use to render itself.\r\n * @method\r\n * @param {TState} state The current state of the component.\r\n * @param {any} ownProps The set of properties that is passed in from where the component is created.\r\n * This parameter should be not nil only when the component is supposed to have part of its properties coming from a parent component.\r\n * It can be omitted when the entire set of props is derived from the state.\r\n * @returns {mapStateToPropsReturnType} It can either return the set of mapped props as an object of type TProps derived from a state\r\n * object of type TState or a function that will be used to map the state to the props.\r\n */\r\n public abstract mapStateToProps(state: TState, ownProps?: any): mapStateToPropsReturnType;\r\n\r\n /**\r\n * Inject into props redux action creators.\r\n * @method\r\n * @param {Dispatch} dispatch The redux dispatch function.\r\n * @param {any} ownProps The set of properties that is passed from where the component is created.\r\n * This parameter should be not nil only when the component is supposed to have part of its properties coming from a parent component.\r\n * It can be omitted when the entire set of props is derived from the state.\r\n * @returns {TProps} An enriched set of props.\r\n */\r\n public mapDispatchToProps(dispatch: Dispatch, ownProps?: any): mapDispatchToPropsReturnType {\r\n return {} as TProps;\r\n }\r\n\r\n /**\r\n * Overrides the default redux mergeProps function that will add a callback function for reporting experience milestone timing\r\n * @method\r\n * @param {TState} stateProps The set of properties from mapStateToProps.\r\n * @param {TProps} dispatchProps The set of properties from mapDispatchToProps.\r\n * @param {any} ownProps The set of properties that is passed from where the component is created.\r\n * @returns {TProps} The merged set of props.\r\n */\r\n public mergeProps(stateProps: TProps, dispatchProps: TProps, ownProps: any): TProps {\r\n // WARNING WARNING WARNING. Some render engines, like preact will take dependencies on some props that may be set to undefined, so the\r\n // merge must preserve properties that are undefined in the source (i.e stateProps) in the result.\r\n // Specific to preact depends on the constructor property being explicity set to undefined. When an element is created by preact\r\n // the constructor property is set to undefined, and that must be preserved by this merge function.\r\n // Avoid using lodash merge, as it does not preserve the undefined properties\r\n\r\n // If we are in Mns Creator Dashboard mode, then set props for the config href, and experience type. These will get rendered\r\n // on each experience as unhandled props\r\n let mnsDashBoardProps = {};\r\n if (appEnvironment.ShowMnsCreatorDashboard) {\r\n mnsDashBoardProps = {\r\n \"data-config-href\": this.configHref,\r\n \"data-experience-type\": this.experienceType\r\n };\r\n }\r\n\r\n // The onExperienceMilestonTimingUpdate prop is set here, so that it is injected into the resulting properties for all experiences.\r\n return {\r\n onExperienceMilestoneTimingUpdate: this.onExperienceMilestoneTimingUpdate,\r\n ...mnsDashBoardProps,\r\n ...ownProps,\r\n ...stateProps,\r\n ...dispatchProps\r\n };\r\n }\r\n\r\n /**\r\n * Connects the passed in component to the redux store/state of the connector\r\n * @method\r\n * @param {React.ComponentType} componentToConnect The react element to connect.\r\n * @param {any} connectorProps Optional connector props to pass to the onComponentConnect call.\r\n * @returns {React.ComponentClass} The Redux connected component.\r\n */\r\n public async connectComponent(componentToConnect: React.ComponentType, connectorProps?: ExperienceInitialProps): Promise> {\r\n\r\n // If we are not online, and we should not render offline, then just return undefined. This will prevent the experience from ever\r\n // rendering\r\n if (canUseDOM() && !navigator.onLine && !this.$renderIfOffline) {\r\n return undefined;\r\n }\r\n\r\n const connectMeasureEnd = this.perfTimeline && this.perfTimeline.startMeasure(\"connect\").endMeasure;\r\n\r\n // Call the onComponentConnect method. This is done first, so that the connector can see the initialProps before mapStateToProps is called\r\n // onComponentConnect is async, so we need to wait for it to complete first\r\n await this.onComponentConnect(connectorProps);\r\n\r\n // if this experience should be instrumented for perf, do so and get the perf HOC\r\n if (this.perfTimeline) {\r\n componentToConnect = instrumentPerf(componentToConnect, this.perfTimeline);\r\n this.mapStateToProps = this.perfTimeline.instrumentFunc(\"mapStateToProps\", this.mapStateToProps, this);\r\n this.mapDispatchToProps = this.perfTimeline.instrumentFunc(\"mapDispatchToProps\", this.mapDispatchToProps, this);\r\n this.mergeProps = this.perfTimeline.instrumentFunc(\"mergeProps\", this.mergeProps, this);\r\n }\r\n\r\n // Connect the component to redux (will cause mapStateToProps to be called)\r\n const connectedComponent: React.ComponentClass = connect(\r\n this.mapStateToProps.bind(this),\r\n this.mapDispatchToProps.bind(this),\r\n this.mergeProps.bind(this),\r\n { pure: true }\r\n )(componentToConnect);\r\n\r\n // Wrap the redux connected component in a Subspace Provider, and set that as the connectedComponent for this connector\r\n this.$connectedComponent = subspaced(this.selectComponentState, this.namespace)(connectedComponent);\r\n\r\n if (connectMeasureEnd) {\r\n connectMeasureEnd();\r\n }\r\n\r\n return this.$connectedComponent;\r\n }\r\n\r\n /**\r\n * This method reads the experience config and adds any ordinal(index) based child experiences specified in the config to the input\r\n * ChildExperienceConfigInfo array at the specified ordinal position defined in config.\r\n * @method\r\n * @param {ExperienceLoadInfo[]} ExperienceLoadInfoList Array of ChildExperienceConfigInfo objects\r\n * @param {number} mergeStartPosition MergeStartPosition represents the start position for the merge. If your experience only need to call this once,\r\n * it should be 1. For deep river kind of scenario, you would need to pass the updated merge start position. StartPosition = lastEndPosition + 1\r\n * @returns {ExperienceLoadInfo[]}\r\n */\r\n public mergeOrdinalChildExperiences(experienceInfoList: ExperienceLoadInfo[], mergeStartPosition: number,\r\n callback?: (experienceInfo: ExperienceLoadInfo) => void): ExperienceLoadInfo[] {\r\n if (!experienceInfoList) {\r\n return null;\r\n }\r\n\r\n if (mergeStartPosition < 1) {\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ComponentConnectorAppErrors.ListStartPositionInvalid,\r\n message: \"listStartFrom must be greater than 0.\"\r\n });\r\n\r\n return experienceInfoList;\r\n }\r\n\r\n const config = this.config as BaseExperienceConfig;\r\n\r\n if (!config.additionalChildExperiences || config.additionalChildExperiences.length === 0) {\r\n return experienceInfoList;\r\n }\r\n\r\n const ordinalBlockForCurrentColumn = this.getOrdinalObjectForCurrentBreakpoint(config.additionalChildExperiences);\r\n let mergeEndPos = mergeStartPosition + experienceInfoList.length;\r\n\r\n // Following code loops through the ChildArrangementMetadata array and inserts an additional child experience if startPosition provided in config is greater than mergeStartPosition\r\n // and less than mergeEndPos which is mergeStartPosition + length of the input childConfigInfoList\r\n ordinalBlockForCurrentColumn.children.forEach((childArrangementMetadata) => {\r\n const childExpArrangement = childArrangementMetadata.arrangement;\r\n\r\n // TS requires to define this explicitly and then assign it in line 234.\r\n const positionProps: ExperienceInitialPositionProps = { experienceArrangement: childExpArrangement };\r\n\r\n if (childExpArrangement && childExpArrangement.startPosition >= mergeStartPosition && childExpArrangement.startPosition <= mergeEndPos) {\r\n const insertAt = childExpArrangement.startPosition - mergeStartPosition;\r\n const experienceInfo: ExperienceLoadInfo = {\r\n configInfo: childArrangementMetadata.childExperienceConfigInfo,\r\n initialProps: positionProps\r\n };\r\n\r\n experienceInfoList.splice(insertAt, 0, experienceInfo);\r\n mergeEndPos++;\r\n\r\n if (typeof callback === \"function\") {\r\n callback(experienceInfo);\r\n }\r\n }\r\n });\r\n\r\n return experienceInfoList;\r\n }\r\n\r\n /**\r\n * This method is called when a component is connected to the connectors' store.\r\n * This method can be overridden and used by connectors to perform one time initialization functions\r\n * @method\r\n * @param {any} connectorProps Optional initial props passed into the onComponentConnect call.\r\n * @returns {void}\r\n */\r\n public async onComponentConnect(connectorProps?: ExperienceInitialProps): Promise {\r\n\r\n // save the last connected connector props\r\n this.$connectorProps = connectorProps;\r\n\r\n if (connectorProps) {\r\n\r\n // Setup telemetry props for this experience.\r\n if (connectorProps.parentTelemetry\r\n && !isEmpty(connectorProps.parentTelemetry)) {\r\n\r\n // Generate the telemetry props for this experience. These will also be the parent props for any child experiences\r\n this.telemetryProps = Telemetry.getChildTelemetryItem(\r\n connectorProps.parentTelemetry,\r\n this.$experienceType,\r\n TelemetryTypes.Module\r\n );\r\n\r\n // generate the telemetry tags to pass along for rendering\r\n this.telemetryTags = Telemetry.render(this.telemetryProps);\r\n }\r\n\r\n // Override the onAppError function if passed one.\r\n if (isFunction(connectorProps.onAppErrorCallback)) {\r\n this.onAppError = connectorProps.onAppErrorCallback;\r\n }\r\n }\r\n\r\n // load data connectors\r\n // Experiences relying on looking up data connectors need await here. Data Connectors should not have any blocking calls\r\n // in the constructor.\r\n await this.loadDataConnectors();\r\n\r\n for (let injectedDataConnector of this.injectedDataConnectors) {\r\n // Setup the initial state\r\n CommonActions.dataConnectorMergeInit.getActionSender(this).send(injectedDataConnector);\r\n\r\n // Register the merge so we get updates\r\n dataConnectorInjector.registerInjection(this.fullNamespace, injectedDataConnector);\r\n }\r\n\r\n // load up child experiences\r\n await this.onLoadChildExperiences();\r\n }\r\n\r\n /**\r\n * Gets a new instance of a ReactElement for the connected Component for this connector, that can be used to render\r\n * the experience.\r\n * This method will replace any existing ReactElement instance that has been previously created.\r\n * @param ownProps optional props to be passed into the connected components' mapStateToProps method\r\n */\r\n public getNewComponentInstance(ownProps?: TProps): React.ReactElement {\r\n // If there is a connected component for this connector, then create an instance of it.\r\n if (this.$connectedComponent) {\r\n const newProps = { ...ownProps, key: this.namespace };\r\n this.$componentInstance = React.createElement(this.$connectedComponent, newProps);\r\n }\r\n\r\n return this.$componentInstance;\r\n }\r\n\r\n /**\r\n * Report a milestone timing event\r\n * @param milestoneType The type of milestone timing is being reported for\r\n * @param startTime The start time (if defined)\r\n * @param endTime The end time (if defined)\r\n */\r\n protected onExperienceMilestoneTimingUpdate = (milestoneType: ExperienceMilestoneEventTypes,\r\n startTime?: number,\r\n endTime?: number) => {\r\n\r\n // Do a onetime check to get the Milestone Data Connector instance\r\n if (this.$milestoneDataConnector === undefined) {\r\n this.$milestoneDataConnector = getMilestoneDataConnector();\r\n if (this.$milestoneDataConnector === undefined) {\r\n this.$milestoneDataConnector = null; // Set it explicitly to null, so that we don't try to keep getting it\r\n return;\r\n }\r\n }\r\n\r\n // Skip the Milestone update if we don't have a Milestone Data connector\r\n if (!this.$milestoneDataConnector) {\r\n return;\r\n }\r\n\r\n switch (milestoneType) {\r\n case ExperienceMilestoneEventTypes.domComplete:\r\n if (endTime) {\r\n MilestoneDataActions.updateDomCompleteTiming.getActionSender(this.$milestoneDataConnector).send(\r\n this.$experienceType,\r\n this.$experienceGroup,\r\n this.namespace,\r\n startTime,\r\n endTime);\r\n } else {\r\n MilestoneDataActions.updateDomCompleteTiming.getActionSender(this.$milestoneDataConnector).send(\r\n this.$experienceType,\r\n this.$experienceGroup,\r\n this.namespace,\r\n startTime);\r\n }\r\n break;\r\n\r\n case ExperienceMilestoneEventTypes.initialized:\r\n if (endTime) {\r\n MilestoneDataActions.updateInitTiming.getActionSender(this.$milestoneDataConnector).send(\r\n this.$experienceType,\r\n this.$experienceGroup,\r\n this.namespace,\r\n startTime,\r\n endTime);\r\n } else {\r\n MilestoneDataActions.updateInitTiming.getActionSender(this.$milestoneDataConnector).send(\r\n this.$experienceType,\r\n this.$experienceGroup,\r\n this.namespace,\r\n startTime);\r\n }\r\n break;\r\n\r\n case ExperienceMilestoneEventTypes.rendered:\r\n if (endTime) {\r\n MilestoneDataActions.updateRenderTiming.getActionSender(this.$milestoneDataConnector).send(\r\n this.$experienceType,\r\n this.$experienceGroup,\r\n this.namespace,\r\n startTime,\r\n endTime);\r\n } else {\r\n MilestoneDataActions.updateRenderTiming.getActionSender(this.$milestoneDataConnector).send(\r\n this.$experienceType,\r\n this.$experienceGroup,\r\n this.namespace,\r\n startTime);\r\n }\r\n break;\r\n\r\n case ExperienceMilestoneEventTypes.visuallyReady:\r\n if (endTime) {\r\n MilestoneDataActions.updateVisuallyReadyTiming.getActionSender(this.$milestoneDataConnector).send(\r\n this.$experienceType,\r\n this.$experienceGroup,\r\n this.namespace,\r\n startTime,\r\n endTime);\r\n } else {\r\n MilestoneDataActions.updateVisuallyReadyTiming.getActionSender(this.$milestoneDataConnector).send(\r\n this.$experienceType,\r\n this.$experienceGroup,\r\n this.namespace,\r\n startTime);\r\n }\r\n break;\r\n\r\n default:\r\n // do nothing for the default cause, since there is no default timing that can be updated\r\n logger.log(`Milestone timing update was attempted for an unknown milestone type: ${milestoneType}`);\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * This method reads the experience config and returns child experiences placed using index based position.\r\n * @method\r\n * @returns {ExperienceLoadInfo[]}\r\n */\r\n protected getOrdinalChildExperiences(): ExperienceLoadInfo[] {\r\n const config = this.config as BaseExperienceConfig;\r\n\r\n if (!config.additionalChildExperiences || config.additionalChildExperiences.length === 0) {\r\n return null;\r\n }\r\n\r\n let result: ExperienceLoadInfo[] = [];\r\n const ordinalBlockForCurrentColumn = this.getOrdinalObjectForCurrentBreakpoint(config.additionalChildExperiences);\r\n\r\n ordinalBlockForCurrentColumn.children.forEach((childArrangementMetadata) => {\r\n const childExpArrangement = childArrangementMetadata.arrangement;\r\n\r\n // TS requires to define this explicitly and then assign it in line 234.\r\n const positionProps: ExperienceInitialPositionProps = { experienceArrangement: childExpArrangement };\r\n result.push({\r\n configInfo: childArrangementMetadata.childExperienceConfigInfo,\r\n initialProps: positionProps\r\n });\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Loads all the children experiences defined under the configuration in parallel.\r\n * @param config - the base experience config containing the children config info\r\n * @param connectorProps - the initial experience connector props\r\n * @returns {Promise{void}[]} - an array of promises that loads all the children experiences.\r\n */\r\n protected async onLoadChildExperiences(): Promise {\r\n\r\n const baseExperienceConfig = this.config as BaseExperienceConfig;\r\n const childrenConfigInfo: ChildExperienceConfigInfo[] = [];\r\n\r\n // Determine if there are any children in the composition portion of the config document.\r\n if (baseExperienceConfig && baseExperienceConfig.composition) {\r\n\r\n switch (baseExperienceConfig.composition.type) {\r\n case ExperienceCompositionTypes.horizontalStack:\r\n case ExperienceCompositionTypes.layout: {\r\n\r\n // Iterate over the composition config to find the children\r\n const layoutConfig = baseExperienceConfig.composition as LayoutConfig;\r\n\r\n // Iterate over the composition config to find the children\r\n layoutConfig.page.children.forEach(grid => {\r\n\r\n // If the grid does not contain children, then there are no child experiences\r\n if (grid.children === undefined) {\r\n return;\r\n }\r\n\r\n // Iterate over the grid children (each one is a column) and see if there is a child experience\r\n grid.children.forEach((column) => {\r\n\r\n // If the columnProps does not contain children, then there are no child experiences\r\n if (!column.children) {\r\n return;\r\n }\r\n\r\n // If the column.children is a legacy ColumnChildInfo, or of type PeregrineExperience, then\r\n // add the child to the list\r\n const { childType } = column.children as ChildInfo;\r\n if (!childType) {\r\n childrenConfigInfo.push(column.children as ChildExperienceConfigInfo);\r\n } else if (childType === ChildrenTypes.peregrineExperience) {\r\n childrenConfigInfo.push((column.children as PeregrineChildInfo).child);\r\n }\r\n });\r\n });\r\n break;\r\n }\r\n\r\n case ExperienceCompositionTypes.grid: {\r\n\r\n // Iterate over the grid composition config to find the peregrine child experiences to load\r\n const gridRows = (baseExperienceConfig.composition as GridCompositionConfig).grid.rows;\r\n gridRows.forEach(row => {\r\n\r\n // If the row does not contain columns, then there are no child experiences\r\n if (row.columns === undefined) {\r\n return;\r\n }\r\n\r\n // Iterate over the grid columns and see if there are any items\r\n row.columns.forEach((column) => {\r\n // If the column.item is a PeregrineExperience, then add the child to the list of children experiences to load\r\n const { itemType } = column.item;\r\n if (itemType && itemType === ChildrenTypes.peregrineExperience) {\r\n childrenConfigInfo.push(column.item.child as ChildExperienceConfigInfo);\r\n }\r\n });\r\n });\r\n break;\r\n }\r\n\r\n case ExperienceCompositionTypes.customExperience: {\r\n const customConfig = baseExperienceConfig.composition as CustomCompositionConfig;\r\n childrenConfigInfo.push(customConfig.experience);\r\n\r\n break;\r\n }\r\n\r\n // No children to load, if we do not know what type of composition this experience has\r\n default:\r\n }\r\n }\r\n\r\n // Load all the children.\r\n // TODO: passing in the parent's connector props to children verbatim seems wrong.\r\n // However experiences such as spotlight seems to be loading it using this method by\r\n // passing child specific initial props from all the way from the top level page experience,\r\n // so need to resolve that before removing the this.$connectorProps parameter.\r\n await this.loadChildrenExperiences(childrenConfigInfo, this.$connectorProps);\r\n }\r\n\r\n /**\r\n * Load a list of child experiences\r\n * @param children - The list (array) of child experiences to be loaded\r\n * @param childConnectorProps - The connector props to pass to each child experience as it is loaded\r\n * @returns {Promise{void}} - the async operation that denotes loading of all the children.\r\n */\r\n protected async loadChildrenExperiences(children: ChildExperienceConfigInfo[], childConnectorProps?: ExperienceInitialProps): Promise {\r\n if (!children || children.length === 0) {\r\n return;\r\n }\r\n\r\n let childExpsToLoadImmediately = [];\r\n\r\n const reRenderCallback = () => {\r\n this.readyExperienceToRender(children);\r\n };\r\n\r\n for (const child of children) {\r\n let promiseDependency = this.startProcessingChildExperience(child, reRenderCallback, childConnectorProps);\r\n childExpsToLoadImmediately.push(promiseDependency);\r\n }\r\n\r\n // NOTE: In order to make sure that the fail-fast behavior of Promise.all doesn't kick in, we're wrapping the individual promises\r\n // with a catch block and ensuring that they always resolve (never reject/throw error). If we don't do this, then\r\n // even if one child promise gets rejected early, then the parent experience might fail to load the remaining children.\r\n await Promise.all(childExpsToLoadImmediately);\r\n }\r\n\r\n /**\r\n * Gets the list of data connectors to inject into this experience.\r\n */\r\n protected get injectedDataConnectors(): ConnectorNamespaces[] {\r\n return [];\r\n }\r\n\r\n /**\r\n * Load a list of data connectors provided in the experience config\r\n * @returns {Promise{void}} - the async operation that denotes loading of all the children.\r\n */\r\n protected async loadDataConnectors(): Promise {\r\n const baseExperienceConfig = this.config as BaseExperienceConfig;\r\n\r\n // Load any data connectors defined in the config\r\n if (baseExperienceConfig && baseExperienceConfig.dataConnectors && baseExperienceConfig.dataConnectors.length > 0) {\r\n const dataConnectorForCurrentScreenType = this.getOrdinalObjectForCurrentBreakpoint(baseExperienceConfig.dataConnectors);\r\n\r\n if (dataConnectorForCurrentScreenType && dataConnectorForCurrentScreenType.children && dataConnectorForCurrentScreenType.children.length > 0) {\r\n await Promise.all(\r\n dataConnectorForCurrentScreenType.children.map(connector =>\r\n this.loadDataConnector(connector)));\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Loads a single child experience with the given connector initial props.\r\n * @param configInfo - the child experience config info\r\n * @param childConnectorProps - optional initial props to pass to connector.\r\n * @returns {Promise{void}} - the async operation that denotes loading of the child.\r\n */\r\n protected async loadChildExperience(configInfo: ChildExperienceConfigInfo,\r\n childConnectorProps?: ExperienceInitialProps): Promise {\r\n\r\n let childConnector = await this.getChildExperienceConnector(configInfo, childConnectorProps);\r\n\r\n if (!childConnector) {\r\n configInfo.state = ExperienceState.Failed;\r\n return;\r\n }\r\n\r\n this.addConnectorToChildMap(configInfo, childConnector);\r\n }\r\n\r\n /**\r\n * Provides the connector props to be passed into the onComponentConnect method for any children that are created for this\r\n * experience connector\r\n * @param childExperienceType The experience Type of the child experience being loaded\r\n * @param childExperienceInstanceId The experienceInstance Id of the child experience being loaded\r\n */\r\n protected getChildExperienceConnectorProps(childExperienceType: string, childExperienceInstanceId: string): ExperienceInitialProps {\r\n return (\r\n {\r\n parentTelemetry: this.telemetryProps,\r\n context: this.$connectorProps && this.$connectorProps.context,\r\n onAppErrorCallback: this.onAppError\r\n });\r\n }\r\n\r\n /**\r\n * This method returns the ScreenTypeMetadata for current breakpoint.\r\n * @method\r\n * @param {ScreenTypeMetadata[]} screenTypeObjList Array of ScreenTypeMetadata objects\r\n * @returns {ScreenTypeMetadata} returns the matching ScreenTypeMetadata object for current breakpoint.\r\n */\r\n protected getOrdinalObjectForCurrentBreakpoint(screenTypeObjList: ScreenTypeMetadata[]): ScreenTypeMetadata {\r\n switch (fastBreakpointManager.currentColumnArrangement) {\r\n case ColumnArrangement.c1: {\r\n return this.getMetadataByScreenWidth(ScreenWidth.OneColumn, screenTypeObjList);\r\n }\r\n case ColumnArrangement.c2: {\r\n return this.getMetadataByScreenWidth(ScreenWidth.TwoColumn, screenTypeObjList);\r\n }\r\n case ColumnArrangement.c3: {\r\n return this.getMetadataByScreenWidth(ScreenWidth.ThreeColumn, screenTypeObjList);\r\n }\r\n case ColumnArrangement.c4: {\r\n return this.getMetadataByScreenWidth(ScreenWidth.FourColumn, screenTypeObjList);\r\n }\r\n default: {\r\n return this.getMetadataByScreenWidth(ScreenWidth.Any, screenTypeObjList);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * function to call an action to reRender experience\r\n */\r\n protected reRenderExperience(): void {\r\n CommonActions.renderExperience.getActionSender(this).send();\r\n }\r\n\r\n /**\r\n * The optional function for Experiences to call use when an error occurs.\r\n * Defined as empty function so clients don't need to check it.\r\n * Passed to child experiences. Used mainly outside of Peregrine. e.g. Office page.\r\n * NOTE: we need to default to track.trackAppErrorEvent for PH components.\r\n */\r\n protected onAppError: ((error: AppError) => void) = (err) => TelemetryBase.trackAppErrorEvent(err);\r\n\r\n /**\r\n * Helper function to match screenWidth and return the correct ScreenTypeMetadata object\r\n * @method\r\n * @param {ScreenWidth} screenWidth - screenWidth to match\r\n * @param {ScreenTypeMetadata[]} screenTypeObjList - Array of ScreenTypeMetadata objects\r\n * @returns {ScreenTypeMetadata} returns the matching ScreenTypeMetadata object for given screenWidth.\r\n */\r\n private getMetadataByScreenWidth(screenWidth: ScreenWidth, screenTypeObjList: ScreenTypeMetadata[]): ScreenTypeMetadata {\r\n\r\n let result =\r\n screenTypeObjList.find(obj =>\r\n obj.screenWidth === screenWidth\r\n )\r\n || screenTypeObjList.find(obj =>\r\n obj.screenWidth === ScreenWidth.Any\r\n );\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Initializes connector and connected component for a given child experience.\r\n * @param configInfo - the child experience config info\r\n * @param childConnectorProps - optional initial props to pass to connector.\r\n * @returns {Promise>} - the async operation that returns the connector for child experience.\r\n */\r\n private async getChildExperienceConnector(\r\n configInfo: ChildExperienceConfigInfo,\r\n childConnectorProps?: ExperienceInitialProps): Promise> {\r\n\r\n try {\r\n // Get an experience loader instance for the child experience\r\n const { instanceId, href, experienceType } = configInfo;\r\n const loader = new ExperienceLoader(href, instanceId, this.fullNamespace, this.store, experienceType);\r\n\r\n // Get the connector for the child experience, and add it to the child connector map\r\n await loader.loadConnector();\r\n const { connector: childConnector } = loader;\r\n\r\n // Get the connected component for the child experience.\r\n await loader.getConnectedExperience({\r\n // add any override props\r\n ...(childConnectorProps || {}),\r\n // get core connector props\r\n ...this.getChildExperienceConnectorProps(experienceType, instanceId)\r\n });\r\n\r\n // Get the initial component instance for the child. The experience connector can get a new instance if it needs to do special\r\n // processing (i.e. passing in OwnProps)\r\n childConnector.getNewComponentInstance();\r\n\r\n return childConnector;\r\n } catch (error) {\r\n // Remove this config from cache.\r\n resolver.removeCachedConfig(configInfo.href);\r\n\r\n // Log an app error if the loader failed to load for whatever reason\r\n /// NOTE: DO NOT throw Error or reject promise here, or else the parent might not load the remaining child experiences.\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ComponentConnectorAppErrors.BundleLoadError,\r\n message: `Failed to load experience: ${JSON.stringify(configInfo)}, with error: ${error}`\r\n });\r\n\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Load a single data connector\r\n * @param configInfo - data connector config info object\r\n * @returns {Promise{void}} - the async operation that denotes loading of all the children.\r\n */\r\n private async loadDataConnector(configInfo: ChildExperienceConfigInfo): Promise {\r\n\r\n // Get an experience loader instance for the child experience\r\n if (!configInfo || !configInfo.href) {\r\n\r\n // Log an app error if the loader failed to load for whatever reason\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ComponentConnectorAppErrors.BundleLoadError,\r\n message: `Data connector loading failed: ${JSON.stringify(configInfo)}`\r\n });\r\n\r\n return;\r\n }\r\n\r\n const { experienceType } = configInfo;\r\n\r\n try {\r\n const loader = new ExperienceLoader(\r\n // if it's a config-less experience type, do not pass in the HREF to prevent loading the config.\r\n // TODO: after deployment, we need to update configs of config-less connectors so that we don't need\r\n // a special check like this, and instead the empty HREF can be directly set in the config.\r\n // Need to do this in a phased approach so that we don't break PROD users with old scripts.\r\n experienceType && ConfiglessConnectors[experienceType]\r\n ? \"\"\r\n : configInfo.href,\r\n \"\",\r\n \"\",\r\n PageBase.getInstance().store,\r\n experienceType\r\n );\r\n\r\n // Get the connector for the child experience, and add it to the child connector map\r\n await loader.loadConnector(true);\r\n } catch (error) {\r\n // Log an app error if the loader failed to load for whatever reason\r\n /// NOTE: DO NOT throw Error or reject promise here, or else the parent might not load the remaining child experiences.\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ComponentConnectorAppErrors.BundleLoadError,\r\n message: `Failed to load data connector: ${JSON.stringify(configInfo)}, with error: ${error}`\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Select and return the proper inner state for the component. The base DataConnector manages the wrapping of the state\r\n * and so it's getCurrentState() method is used to get the inner state (TState) for the connected component\r\n * NOTE: The signature of this component requires a state parameter, so that it can be passed into the subspaced()\r\n * method that is used to connect the component to state\r\n * @param state For this implementation, this parameter is ignored, since the actual state is managed by the base DataConnector\r\n */\r\n private selectComponentState(state: TParentState): TState {\r\n return (this.getCurrentState());\r\n }\r\n\r\n /**\r\n * Start lifecycle of a child experience\r\n * @param configInfo - the child experience config info\r\n * @param reRenderCallback - Render callback to call when dependencies are resolved\r\n * @param childConnectorProps - child experience connector props\r\n * @returns {Promise{void}} - the async operation that denotes loading of the child.\r\n */\r\n private async startProcessingChildExperience(\r\n configInfo: ChildExperienceConfigInfo,\r\n reRenderCallback: () => void,\r\n childConnectorProps?: ExperienceInitialProps): Promise {\r\n const milestoneDependencyToLoadChildExp = getExperienceLoadDelegate(configInfo.experienceType);\r\n\r\n if (milestoneDependencyToLoadChildExp && milestoneDependencyToLoadChildExp.shouldResolve) {\r\n let addTimeout = true;\r\n\r\n if (milestoneDependencyToLoadChildExp.deferralType === DeferralEventType.CustomEventBasedDeferral) {\r\n addTimeout = false;\r\n configInfo.state = ExperienceState.Unknown;\r\n }\r\n\r\n this.resolveDependency(configInfo, milestoneDependencyToLoadChildExp.shouldResolve, () => {\r\n this.loadAndRenderExperience(configInfo, reRenderCallback, true, childConnectorProps);\r\n }, addTimeout);\r\n } else {\r\n await this.loadAndRenderExperience(configInfo, reRenderCallback, false, childConnectorProps);\r\n }\r\n }\r\n\r\n /**\r\n * load and render experience\r\n * @param childExpInfo - the child experience config info\r\n * @param reRenderCallback - Render callback to call when dependencies are resolved\r\n * @param delayLoaded - whether this experience is delay loaded or not\r\n * @param childConnectorProps - child experience connector props\r\n * @returns {Promise{void}} - the async operation that denotes loading of the child.\r\n */\r\n private async loadAndRenderExperience(\r\n childExpInfo: ChildExperienceConfigInfo,\r\n reRenderCallback: () => void,\r\n delayLoaded: boolean,\r\n childConnectorProps?: ExperienceInitialProps): Promise {\r\n // Get an experience loader instance for the child experience\r\n if (!childExpInfo\r\n || !childExpInfo.href\r\n || !childExpInfo.instanceId) {\r\n\r\n // Log an app error if the loader failed to load for whatever reason\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ComponentConnectorAppErrors.BundleLoadError,\r\n message: `Attempted to load child with invalid experience config: ${JSON.stringify(childExpInfo)}`\r\n });\r\n\r\n return;\r\n }\r\n\r\n try {\r\n const connector = await this.getChildExperienceConnector(childExpInfo, childConnectorProps);\r\n\r\n if (!connector) {\r\n childExpInfo.state = ExperienceState.Failed;\r\n return;\r\n }\r\n\r\n const milestoneDependencyToRenderChildExp = getExperienceRenderDelegate(childExpInfo.experienceType);\r\n\r\n if (milestoneDependencyToRenderChildExp && milestoneDependencyToRenderChildExp.shouldResolve) {\r\n this.resolveDependency(childExpInfo, milestoneDependencyToRenderChildExp.shouldResolve, () => {\r\n childExpInfo.state = ExperienceState.ReadyToRender;\r\n this.addConnectorToChildMap(childExpInfo, connector);\r\n reRenderCallback();\r\n }, true);\r\n } else {\r\n childExpInfo.state = ExperienceState.ReadyToRender;\r\n this.addConnectorToChildMap(childExpInfo, connector);\r\n if (delayLoaded) {\r\n reRenderCallback();\r\n }\r\n }\r\n } catch (error) {\r\n childExpInfo.state = ExperienceState.Failed;\r\n // Log an app error if the loader failed to delayload\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ComponentConnectorAppErrors.ChildDelayLoadError,\r\n message: `Attempted to delay load child ${JSON.stringify(childExpInfo.experienceType)} and failed as associated deferral promise returned an error : ${JSON.stringify(error)}`\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * add connector to child map\r\n * @param configInfo - the child experience config info\r\n * @param childConnector - child experience connector\r\n */\r\n private addConnectorToChildMap(configInfo: ChildExperienceConfigInfo, childConnector: IComponentConnector): void {\r\n // If the experience loaded, and we got the connected component, then add it to the child map,\r\n // as long as we have not seen this child before\r\n if (!this.childMap.has(configInfo.instanceId)) {\r\n this.childMap.set(configInfo.instanceId, childConnector);\r\n } else {\r\n // Log an app error\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ComponentConnectorAppErrors.DuplicateChildInstanceFound,\r\n message: `Duplicate child instance found: ${childConnector.namespace}`,\r\n pb: {\r\n ...ComponentConnectorAppErrors.DuplicateChildInstanceFound.pb,\r\n customMessage: `href: ${location && location.href}, parentNamespace: ${this.fullNamespace}`\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Check if delay loaded experiences are ready to be rendered\r\n * @param children - the child experience config info array\r\n */\r\n private readyExperienceToRender(children: ChildExperienceConfigInfo[]): void {\r\n const config = this.config as BaseExperienceConfig;\r\n let reRender = true;\r\n\r\n if (!config.childExperiencesRenderType || config.childExperiencesRenderType === ChildExperiencesDeferRenderType.batch) {\r\n for (const child of children) {\r\n if (child.state !== ExperienceState.ReadyToRender && child.state !== ExperienceState.Failed && child.state !== ExperienceState.Unknown) {\r\n reRender = false;\r\n }\r\n }\r\n }\r\n\r\n if (reRender) {\r\n this.reRenderExperience();\r\n }\r\n }\r\n\r\n /**\r\n * Resolves promise dependency with applicable timeout strategy\r\n * @param dependency - Delegate Promise to resolve dependency\r\n * @param callback - callback function to call when depdendency is resolved\r\n */\r\n private resolveDependency(configInfo: ChildExperienceConfigInfo,\r\n dependency: () => Promise,\r\n callback: () => void,\r\n addTimeout: boolean): void {\r\n let pending = true;\r\n let timer: NodeJS.Timer = null;\r\n\r\n if (addTimeout) {\r\n timer = setTimeout(() => {\r\n if (pending) {\r\n pending = false;\r\n callback();\r\n TelemetryBase.trackEvent({\r\n ...ComponentConnectorAppErrors.ExperienceDependencyTimeout,\r\n message: `Milestone depdendency failed to resolve. Timeout occured for ${JSON.stringify(configInfo.experienceType)}`\r\n });\r\n }\r\n }, this.$maxWaitToBatchRenderChildExperiences);\r\n }\r\n\r\n dependency().then(() => {\r\n if (addTimeout) {\r\n clearTimeout(timer);\r\n }\r\n\r\n if (pending) {\r\n pending = false;\r\n callback();\r\n }\r\n });\r\n }\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { PerfTimeline } from \"@msnews/diagnostics\";\r\nimport React from \"react\";\r\n\r\n/**\r\n * Returns an HOC for tracking perf timeline of a React.Component\r\n * @param WrappedComponent - the component to instrument perf for\r\n * @param perfTimeline - the {PerfTimeline} object to use for tracking perf.\r\n * This is normally created in the parent context when instantating the component\r\n * and passed down to the HOC.\r\n */\r\nexport function instrumentPerf(\r\n WrappedComponent: React.ComponentType,\r\n perfTimeline: PerfTimeline\r\n): React.ComponentClass {\r\n\r\n return class ComponentPerfTimeline extends React.Component {\r\n\r\n /**\r\n * The last render action's endMeasure method to be used to mark the end of the render\r\n * cycle when mount or update happens next\r\n */\r\n private lastRenderEndMeasure: () => void;\r\n\r\n /** React render lifecycle handler */\r\n public render(): JSX.Element {\r\n this.lastRenderEndMeasure = perfTimeline.startMeasure(\"render\").endMeasure;\r\n return ;\r\n }\r\n\r\n /** React componentDidMount lifecycle handler */\r\n public componentDidMount(): void {\r\n this.lastRenderEndMeasure();\r\n }\r\n\r\n /** React componentDidUpdate lifecycle handler */\r\n public componentDidUpdate(): void {\r\n this.lastRenderEndMeasure();\r\n }\r\n };\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Constants used for Prime Integration\r\n */\r\nexport const PrimeIntegrationConstants = {\r\n\r\n /**\r\n * Default value we use for the name of the cookie that holds the ANID\r\n */\r\n AnonCookieName: \"APP_ANON\",\r\n\r\n /** The ID of the coachmark to show for when a user performed follow/unfollow action fails */\r\n userActionErrorCoachMarkId: \"cm-spafeedsapp-user-action-error\"\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { MediatorEventNames } from \"./MediatorEventNames\";\r\nimport { PrimeIntegrationConstants } from \"./Constants\";\r\nimport { SubnavTabId } from \"./SubnavTabId\";\r\nimport { TabsHelper } from \"./SubnavTabHelper\";\r\nimport { getMediator } from \"mediator-integration\";\r\nimport { logger } from \"@msnews/diagnostics\";\r\n\r\nexport namespace Mediator {\r\n /**\r\n * API to listen for tab change event from Prime\r\n *\r\n * @export\r\n * @param callback {(tabId: number) => void} - A callback method to handle the event\r\n * @param shouldCallTabChangeEventImmediately {Boolean} - if we should immediately call the callback in order to capture any changes between initialization and registration.\r\n * @return Promise\r\n */\r\n export async function registerForTabChangeEvent(callback: (tabId: number) => void, shouldCallCallbackImmediately: boolean = false): Promise {\r\n try {\r\n const mediator = await getMediator();\r\n\r\n function sendActiveTabToCallback(data: PrimeGlobal.INavigateEventData): void {\r\n let activeTab: SubnavTabId = getActiveTabValue();\r\n\r\n // This is only used if the caller of the mediator event neglected to set window.navigation and if the caller decides to use \"tab\" instead of \"tabId\"\r\n if (activeTab === SubnavTabId.None && data && data.tab) {\r\n activeTab = data.tab;\r\n }\r\n\r\n if (window._perfMarker) {\r\n window._perfMarker(\"TimeToTabClick_\" + TabsHelper.tabIdToTabName(activeTab), true);\r\n }\r\n\r\n callback(activeTab);\r\n }\r\n\r\n mediator.sub(MediatorEventNames.TabNavigation, sendActiveTabToCallback);\r\n if (shouldCallCallbackImmediately) {\r\n sendActiveTabToCallback(null);\r\n }\r\n } catch {\r\n logger.logError(\"Couldn't load the mediator object.\");\r\n }\r\n }\r\n\r\n /**\r\n * API to listen for content actions updates from Prime\r\n *\r\n * @export\r\n * @param callback {()) => void} - A callback method to handle the event\r\n * @return Promise\r\n */\r\n export async function registerContentActionsUpdatedEvent(callback: () => void): Promise {\r\n try {\r\n const mediator = await getMediator();\r\n mediator.sub(MediatorEventNames.ContentActionsUpdated, callback);\r\n } catch {\r\n logger.logError(\"Couldn't load the mediator object.\");\r\n }\r\n }\r\n\r\n /**\r\n * API to listen for card action enable event from Prime\r\n *\r\n * @export\r\n * @param callback {(initData PrimeGlobal.ICardActionInitEventData)) => void} - A callback method to handle the event\r\n * @return Promise\r\n */\r\n export async function registerCardActionEnableEvent(callback: (initData: PrimeGlobal.ICardActionInitEventData) => void): Promise {\r\n try {\r\n const mediator = await getMediator();\r\n mediator.sub(MediatorEventNames.CardActionInit, (initData: PrimeGlobal.ICardActionInitEventData): void => {\r\n callback(initData);\r\n });\r\n } catch {\r\n logger.logError(\"Couldn't load the mediator object.\");\r\n }\r\n }\r\n\r\n /**\r\n * API to listen for card action post event from Prime\r\n *\r\n * @export\r\n * @param callback {(initData PrimeGlobal.ICardActionPostEventData)) => void} - A callback method to handle the event\r\n * @return Promise\r\n */\r\n export async function registerCardActionPostEvent(callback: (postData: PrimeGlobal.ICardActionPostEventData) => void): Promise {\r\n try {\r\n const mediator = await getMediator();\r\n mediator.sub(MediatorEventNames.CardActionPost, (postData: PrimeGlobal.ICardActionPostEventData): void => {\r\n callback(postData);\r\n });\r\n } catch {\r\n logger.logError(\"Couldn't load the mediator object.\");\r\n }\r\n }\r\n\r\n /**\r\n * API to listen for follow button click event from Prime\r\n *\r\n * @export\r\n * @param callback {(topicId: string, isFollowed: boolean) => void} - A callback method to handle the event\r\n * @return Promise\r\n */\r\n export async function registerForFollowButtonClickEvent(callback: (topicId: string, isFollowed: boolean) => void): Promise {\r\n try {\r\n const mediator = await getMediator();\r\n mediator.sub(MediatorEventNames.TopicAction, function (followButtonData: PrimeGlobal.IFollowButtonClickData): void {\r\n if (followButtonData && followButtonData.topicId) {\r\n callback(followButtonData.topicId, followButtonData.isFollowed);\r\n }\r\n });\r\n } catch {\r\n logger.logError(\"Couldn't load the mediator object.\");\r\n }\r\n }\r\n\r\n /**\r\n * API to listen for Interests render complete event.\r\n *\r\n * @export\r\n * @return Promise\r\n */\r\n export async function registerForInterestsRenderCompleteEvent(callback: () => void): Promise {\r\n try {\r\n const mediator = await getMediator();\r\n mediator.sub(MediatorEventNames.InterestsRenderComplete, function (): void {\r\n callback();\r\n });\r\n } catch {\r\n logger.logError(\"Couldn't load the mediator object.\");\r\n }\r\n }\r\n\r\n /**\r\n * Returns the active tab\r\n * @public\r\n * @return {SubnavTabId}\r\n */\r\n export function getActiveTabValue(): SubnavTabId {\r\n let activeTabValue: string = \"\";\r\n\r\n if (window.navigation && typeof window.navigation.activeTab === \"string\") {\r\n activeTabValue = window.navigation.activeTab.toLowerCase();\r\n }\r\n\r\n return TabsHelper.tabNameToTabId(activeTabValue);\r\n }\r\n\r\n /**\r\n * API to publish the event to Prime.\r\n *\r\n * @export\r\n * @param event - the mediator event name string\r\n * @param data - the event data\r\n * @return Promise\r\n */\r\n export async function publishEventForPrime(event: string, data?: any): Promise {\r\n try {\r\n const mediator = await getMediator();\r\n mediator.pub(event, data);\r\n } catch {\r\n logger.logError(\"Couldn't load the mediator object in publishEventForPrime.\");\r\n }\r\n }\r\n\r\n /**\r\n * Publishes a message to trigger rendering of a mediated coach mark from Prime page\r\n * @param refElement {Element} - the reference element next to which the coachmark should be rendered. This is optional for Overlay type of coachmarks\r\n * @param hideCoachMark {boolean} - flag to indicate whether to hide the coachmark. Default value of false indicates that the coachmark should be shown.\r\n * @returns Promise{void} - The promise that will return after the action has been completed.\r\n */\r\n export async function renderUserActionErrorCoachmark(\r\n args: { refElement?: Element, hideCoachMark?: boolean } = {}): Promise {\r\n\r\n args = {\r\n refElement: undefined,\r\n hideCoachMark: false,\r\n ...args\r\n };\r\n\r\n const mediator = await getMediator();\r\n mediator.pub(\r\n MediatorEventNames.MediatedCoachMark,\r\n {\r\n coachMarkId: PrimeIntegrationConstants.userActionErrorCoachMarkId,\r\n refElement: args.refElement,\r\n hideCoachMark: args.hideCoachMark\r\n });\r\n }\r\n}","\r\n// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { renderCacheExpirationKey, renderCacheKey, riverRcClassName } from \"./Constants\";\r\n\r\nimport { RenderCache } from \"./RenderCache\";\r\n\r\nlet renderCacheObject: RenderCache;\r\n\r\n/**\r\n * Function to get render cache if it's valid.\r\n * @returns Render cache object if it exists and is valid otherwise null.\r\n */\r\nexport function getRenderCache(): RenderCache {\r\n if (renderCacheObject) {\r\n return renderCacheObject;\r\n }\r\n\r\n if (!(window && window.localStorage)) {\r\n return null;\r\n }\r\n\r\n const cacheExpirationTimestamp = window.localStorage.getItem(renderCacheExpirationKey);\r\n\r\n if (!cacheExpirationTimestamp) {\r\n return null; // Cache Expiration Timestamp not exist\r\n }\r\n\r\n const parsedCacheExpirationTimestamp = parseInt(cacheExpirationTimestamp);\r\n if (!parsedCacheExpirationTimestamp) {\r\n return null; // Cache Expiration Timestamp broken.\r\n }\r\n\r\n const currentTimestamp: number = new Date().getTime();\r\n\r\n if (currentTimestamp >= parsedCacheExpirationTimestamp) {\r\n return null; // cache expired.\r\n }\r\n\r\n const renderCacheStorage = window.localStorage.getItem(renderCacheKey);\r\n\r\n if (!renderCacheStorage) {\r\n return null; // Cache object is missing.\r\n }\r\n\r\n try {\r\n renderCacheObject = JSON.parse(renderCacheStorage);\r\n } catch (error) {\r\n return null; // Cache object not parsable.\r\n }\r\n\r\n if (!renderCacheObject || !renderCacheObject.dom || !renderCacheObject.batch_css) {\r\n renderCacheObject = null; // Cache object is broken\r\n }\r\n\r\n return renderCacheObject;\r\n}\r\n\r\n/**\r\n * Batch All styles into one object.\r\n */\r\nexport function batchCSS(): string {\r\n let batchCss = \"\";\r\n\r\n // Enumerate and write out all of the JSS styles\r\n const styles = document.getElementsByTagName(\"style\");\r\n const length = styles.length;\r\n\r\n for (var i = 0; i < length; i++) {\r\n // Skip any styles that do not have a data-jss attribute to always pick newer styles added by jss\r\n if (styles[i].dataset.jss != null) {\r\n batchCss += styles[i].innerHTML;\r\n }\r\n }\r\n\r\n return batchCss;\r\n}\r\n\r\n/**\r\n * Scrapes Dom and remove River.\r\n */\r\nexport function scrapeDom(includeNewsFeed: boolean): string {\r\n const root = document.getElementById(\"root\");\r\n\r\n if (!root || !root.innerHTML) {\r\n return \"\";\r\n }\r\n\r\n /* Currently we don't have functionality to include experiences separately,\r\n because of that we do return whole dom if river included in render cache and exclude river otherwise */\r\n if (includeNewsFeed) {\r\n return root.innerHTML;\r\n }\r\n\r\n const rivers = document.getElementsByClassName(riverRcClassName);\r\n\r\n if (!rivers || !rivers.length) {\r\n return root.innerHTML;\r\n }\r\n\r\n const river = rivers[0] as HTMLElement;\r\n\r\n return root.innerHTML.replace(river.outerHTML, \"\");\r\n}\r\n\r\n/**\r\n * Gets the state object from render cache.\r\n * @returns The redux state object.\r\n */\r\nexport function getStateFromRenderCache(): any {\r\n // Check to see if this app instance was bootstrapped with a render-cache\r\n const renderCache = getRenderCache();\r\n\r\n if (!renderCache || !renderCache.state) {\r\n return null; // Render Cache missing or it does not include State.\r\n }\r\n\r\n let initialState;\r\n\r\n try {\r\n initialState = JSON.parse(renderCache.state, reduxStoreStringifyReviver);\r\n } catch (error) {\r\n // Cache state object is not parsable.\r\n }\r\n\r\n return initialState;\r\n}\r\n\r\n/**\r\n * Redux Store Stringify replacer HOF, generates store stringify.\r\n * @param storeExceptions list of store namespaces which will not be included in result.\r\n */\r\nexport function reduxStoreStringifyReplacer(key: string, value: any): any {\r\n const originalObject = this[key];\r\n if (originalObject instanceof Map) {\r\n return { dataType: \"Map\",\r\n value: [...originalObject]\r\n };\r\n } else {\r\n return value;\r\n }\r\n}\r\n\r\n/**\r\n * Custom JSON.stringify reviver that will create Map objects from a string/JSON representation\r\n * @param key not used\r\n * @param value The value being converted from a string\r\n */\r\nfunction reduxStoreStringifyReviver(key: any, value: any): any {\r\n // If the value being restored is a object, check it it was a map\r\n if (typeof value === \"object\" && value !== null) {\r\n // If the object value being restored was a map, that was custom written, then revive it by creating a map\r\n if (value.dataType === \"Map\") {\r\n return new Map(value.value);\r\n }\r\n }\r\n\r\n // Return the original value being restored\r\n return value;\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { AppError } from \"@msnews/diagnostics\";\r\n\r\n/**\r\n * This is a global tracking object which is used to avoid\r\n * the need to have hard dependencies to a telemetry package.\r\n * Think of this as an interface which is overrided at runtime\r\n * by each app-type.\r\n */\r\n\r\ninterface TelemetryBase {\r\n trackAppErrorEvent(error: AppError): void;\r\n sendSinglePageViewBeacon(beaconId: string): void;\r\n trackPartialImpression(element?: any, visibilityCheck?: boolean, mechanism?: string, topLevelContainerType?: string): void;\r\n trackEvent(event: any,\r\n element?: any,\r\n destination?: any,\r\n headline?: string,\r\n module?: string,\r\n index?: string,\r\n campaign?: string,\r\n contentAction?: number): void;\r\n};\r\n\r\nexport const TelemetryBase: TelemetryBase = {\r\n trackAppErrorEvent: ():void => undefined,\r\n sendSinglePageViewBeacon: ():void => undefined,\r\n trackPartialImpression: ():void => undefined,\r\n trackEvent: ():void => undefined\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { IActivityLogItem } from \"clientcore-infrastructure-analytics/models/IActivityLogItem\";\r\nimport { ILoggingService } from \"clientcore-infrastructure-analytics/ILoggingService\";\r\nimport { LoggedExceptionManager } from \"clientcore-infrastructure-analytics/LoggedExceptionManager\";\r\n\r\n/**\r\n * ExponentialBackoffRetry implements retry logic for transient errors.\r\n * When encountering transient errors, the request is tried again and each retry is delayed exponentially using following calculation:\r\n * Math.min(this.baseRetryDelay * Math.pow(this.factor, retry), this.maxRetryDelay).\r\n * The request is retried until maximum retry count is reached or the request completes successfully or fails with a non-transient error.\r\n * Each delay is offset by a random number between a minimum and maximum offset range, so that in the cases of when there is a failure\r\n * where many clients fail at once (e.g. network outage) there is not a huge amount of requests at the same time to the server.\r\n * @class\r\n */\r\nexport class ExponentialBackoffRetry {\r\n\r\n /**\r\n * Default base delay between each retries.\r\n * @type {number}\r\n */\r\n private static defaultBaseRetryDelayInMs: number = 100;\r\n\r\n /**\r\n * Default exponential factor to use to increase each retry delay.\r\n * @type {number}\r\n */\r\n private static defaultFactor: number = 2;\r\n\r\n /**\r\n * Default maximum offset for each delay.\r\n * @type {number}\r\n */\r\n private static defaultMaxOffsetInMs: number = 25;\r\n\r\n /**\r\n * Default number of retries.\r\n * @type {number}\r\n */\r\n private static defaultMaxRetries: number = 5;\r\n\r\n /**\r\n * Default minimum offset for each delay.\r\n * @type {number}\r\n */\r\n private static defaultMinOffsetInMs: number = 1;\r\n\r\n /**\r\n * Maximum allowed number of retries.\r\n * @type {number}\r\n */\r\n private static maxAllowedRetries: number = 10;\r\n\r\n /**\r\n * Maximum allowed time in milliseconds to delay each retry.\r\n * @type {number}\r\n */\r\n private static maxAllowedRetryDelayInMs: number = 2000;\r\n\r\n /**\r\n * Base delay value in milliseconds to delay each retry.\r\n * Default value is 100.\r\n * @type {number}\r\n */\r\n private baseRetryDelayInMs: number;\r\n\r\n /**\r\n * The exponential factor to use for delaying each subsequent retry.\r\n * Default value is 2.\r\n * @type {number}\r\n */\r\n private factor: number;\r\n\r\n /**\r\n * The logging service\r\n * @type {ILoggingService}\r\n */\r\n private loggingService: ILoggingService;\r\n\r\n /**\r\n * Maximum delay offet in milliseconds.\r\n * Default value is 25.\r\n * @type {number}\r\n */\r\n private maxOffsetInMs: number;\r\n\r\n /**\r\n * Maximum number of retries.\r\n * Default is 5.\r\n * @type {number}\r\n */\r\n private maxRetries: number;\r\n\r\n /**\r\n * Maximum delay in milliseconds between each retry.\r\n * Default value is 2000.\r\n * @type {number}\r\n */\r\n private maxRetryDelayInMs: number;\r\n\r\n /**\r\n * Minimum delay offet in milliseconds.\r\n * Default value is 1.\r\n * @type {number}\r\n */\r\n private minOffsetInMs: number;\r\n\r\n /**\r\n * Initializes a new instance of the 'ExponentialBackoffRetry' class.\r\n *\r\n * @constructor\r\n * @param loggingService {ILoggingService}\r\n * @param maxRetries? {number} The maximum number of times to retry the operation. Default is 5 and maximum value allowed is 10.\r\n * @param baseRetryDelayInMs? {number} The base delay in milliseconds for each retry. Default is 100.\r\n * @param maxRetryDelayInMs? {number} The maximum number of milliseconds between two retries. Default and maximum allowed is 2000.\r\n * @param factor? {number} The exponential factor to use. Default is 2.\r\n * @param minOffsetInMs? {number} The minimum delay in milliseconds offset to use. Default is 1.\r\n * @param maxOffsetInMs? {number} The maximum delay in milliseconds offset to use. Default is 25.\r\n */\r\n constructor(\r\n loggingService: ILoggingService,\r\n maxRetries?: number,\r\n baseRetryDelayInMs?: number,\r\n maxRetryDelayInMs?: number,\r\n factor?: number,\r\n minOffsetInMs?: number,\r\n maxOffsetInMs?: number) {\r\n if (!loggingService) {\r\n throw new Error(\"loggingService is required for ExponentialBackoffRetry.\");\r\n }\r\n\r\n const loggedExceptionManager = new LoggedExceptionManager(loggingService);\r\n\r\n this.logInvalidParams(\r\n loggedExceptionManager,\r\n maxRetries,\r\n baseRetryDelayInMs,\r\n maxRetryDelayInMs,\r\n factor,\r\n maxOffsetInMs\r\n );\r\n\r\n this.loggingService = loggingService;\r\n this.maxRetries = maxRetries || ExponentialBackoffRetry.defaultMaxRetries;\r\n this.baseRetryDelayInMs = baseRetryDelayInMs || ExponentialBackoffRetry.defaultBaseRetryDelayInMs;\r\n this.maxRetryDelayInMs = maxRetryDelayInMs || ExponentialBackoffRetry.maxAllowedRetryDelayInMs;\r\n this.factor = factor || ExponentialBackoffRetry.defaultFactor;\r\n this.minOffsetInMs = minOffsetInMs || ExponentialBackoffRetry.defaultMinOffsetInMs;\r\n this.maxOffsetInMs = maxOffsetInMs || ExponentialBackoffRetry.defaultMaxOffsetInMs;\r\n\r\n this.loggingService.infoCallback(() => \"ExponentialBackoffRetry has been configured.\", null, { maxRetries, minTimeout: baseRetryDelayInMs, maxTimeout: maxRetryDelayInMs, factor });\r\n }\r\n\r\n /**\r\n * Execute given request and retry it as configured.\r\n * @param serviceCall {() => Promise}\r\n */\r\n public async executeRequest(serviceCall: () => Promise, requestInfo?: any, activity?: IActivityLogItem): Promise {\r\n return new Promise(async(resolve, reject) => {\r\n await this.tryRequest(serviceCall, resolve, reject, 0 /* currentRetry is 0 based */, requestInfo, activity);\r\n });\r\n }\r\n\r\n /**\r\n * Log valid params to the class constructor.\r\n *\r\n * @constructor\r\n * @param loggedExceptionManager {LoggedExceptionManager}\r\n * @param maxRetries? {number} The maximum number of times to retry the operation. Default is 5 and maximum value allowed is 10.\r\n * @param baseRetryDelayInMs? {number} The base delay in milliseconds for each retry. Default is 100.\r\n * @param maxRetryDelayInMs? {number} The maximum number of milliseconds between two retries. Default and maximum allowed is 2000.\r\n * @param factor? {number} The exponential factor to use. Default is 2.\r\n */\r\n private logInvalidParams(\r\n loggedExceptionManager: LoggedExceptionManager,\r\n maxRetries?: number,\r\n baseRetryDelayInMs?: number,\r\n maxRetryDelayInMs?: number,\r\n factor?: number,\r\n maxOffsetInMs?: number): void {\r\n if (maxRetries && (maxRetries < 1 || maxRetries > ExponentialBackoffRetry.maxAllowedRetries)) {\r\n loggedExceptionManager.fatal(`maxRetries should be at least 1 and less than ${ExponentialBackoffRetry.maxAllowedRetries}.`);\r\n }\r\n\r\n if (baseRetryDelayInMs && baseRetryDelayInMs < ExponentialBackoffRetry.defaultBaseRetryDelayInMs) {\r\n loggedExceptionManager.fatal(\"baseRetryDelay has to be a positive value greater than or equal to 100.\");\r\n }\r\n\r\n if (baseRetryDelayInMs && maxOffsetInMs && baseRetryDelayInMs <= maxOffsetInMs) {\r\n loggedExceptionManager.fatal(\"baseRetryDelay must not be smaller than the maximum delay offset.\");\r\n }\r\n\r\n if (maxRetryDelayInMs && (maxRetryDelayInMs <= 0 || maxRetryDelayInMs > ExponentialBackoffRetry.maxAllowedRetryDelayInMs)) {\r\n loggedExceptionManager.fatal(`maxRetryDelay has to be a positive value less than ${ExponentialBackoffRetry.maxAllowedRetryDelayInMs}.`);\r\n }\r\n\r\n if (factor && factor <= 0) {\r\n loggedExceptionManager.fatal(\"factor has to be a positive value.\");\r\n }\r\n }\r\n\r\n /**\r\n * Try the request if it fails with a transient error.\r\n * @param serviceCall {() => Promise} The request to execute and retry.\r\n * @param currentRetry {number} current retry count, 0 based.\r\n * @param requestInfo? {TRequestInfo} Additional request info to include in logging.\r\n * @param activity? {IActivityLogItem} Optional activity to associate logged messages with.\r\n * @returns {Promise}\r\n */\r\n private async tryRequest(\r\n serviceCall: () => Promise,\r\n resolve: (result?: any) => void,\r\n reject: (error: any) => void,\r\n currentRetry: number,\r\n requestInfo?: any,\r\n activity?: IActivityLogItem): Promise {\r\n try {\r\n const timeoutInMs = 10000; // Default timeout is 10 sec\r\n const response = await this.timeoutServiceRequest(timeoutInMs, serviceCall());\r\n resolve(response);\r\n } catch (error) {\r\n // Check if the error is transient and retry if we didn't exceed the retry count.\r\n if (currentRetry < this.maxRetries) {\r\n // Offset for delay, in the instance where there is some sort of outage and all clients retry at the same interval. In this case it will stagger the retries.\r\n const fractionDigit = 3;\r\n const offset = parseFloat((Math.random() * (this.minOffsetInMs - this.maxOffsetInMs) + this.maxOffsetInMs).toFixed(fractionDigit));\r\n // Weather to add or subtract the random element.\r\n const half = 0.5;\r\n const plusOrMinus = Math.random() < half ? -1 : 1;\r\n // Delay the retry based on the factor and the current retry count. Do not exceed maximum delay allowed.\r\n const delay = Math.min(this.baseRetryDelayInMs * Math.pow(this.factor, currentRetry), this.maxRetryDelayInMs);\r\n // Offset the delay either positively or negatively by the offset.\r\n const delayWithOffset = delay + (offset * plusOrMinus);\r\n this.loggingService.warnCallback(() => `Retrying the request in ${delayWithOffset} milliseconds.`, activity, { error, currentRetry: currentRetry + 1, requestInfo });\r\n setTimeout(() => this.tryRequest(serviceCall, resolve, reject, currentRetry + 1, requestInfo, activity), delayWithOffset);\r\n } else {\r\n // Give up retrying.\r\n this.loggingService.errorCallback(\r\n () => (currentRetry < this.maxRetries) ? `ExponentialBackoffRetry has exceeded maximum retries ${this.maxRetries}` : \"Request has failed.\",\r\n activity,\r\n { error, currentRetry, requestInfo });\r\n reject(error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Timeout functionality for service call;\r\n * This is not a connection timeout but rather a response timeout\r\n *\r\n * @param {number} timeoutInMs - The timeout in ms\r\n * @param {Promise} promise - The promise for service call\r\n * @return {Promise} - A promise of the service response\r\n */\r\n private async timeoutServiceRequest(timeoutInMs: number, promise: Promise): Promise {\r\n return new Promise(async (resolve, reject) => {\r\n const timeoutId = setTimeout(() => reject(new Error(\"Service Request Timed out!\")), timeoutInMs);\r\n\r\n try {\r\n const response = await promise;\r\n resolve(response);\r\n clearTimeout(timeoutId);\r\n } catch (error) {\r\n reject(error);\r\n clearTimeout(timeoutId);\r\n }\r\n });\r\n }\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ActivityLoggingService } from \"clientcore-infrastructure-analytics/ActivityLoggingService\";\r\nimport { BrowserConsoleAppender } from \"clientcore-infrastructure-analytics/appenders/BrowserConsoleAppender\";\r\nimport { ExponentialBackoffRetry } from \"@msnews/core\";\r\nimport { IInstrumentationService } from \"clientcore-infrastructure-analytics/IInstrumentationService\";\r\nimport { InstrumentationService } from \"clientcore-infrastructure-analytics/InstrumentationService\";\r\nimport { LogLevel } from \"clientcore-infrastructure-analytics/models/LogLevel\";\r\nimport { OneServiceUtility } from \"./OneServiceUtility\";\r\nimport { logger } from \"@msnews/diagnostics\";\r\n\r\n/**\r\n * Instrumentation service\r\n *\r\n * @type {IInstrumentationService}\r\n */\r\nlet instrumentationService: IInstrumentationService;\r\n\r\n/**\r\n * Retry manager\r\n *\r\n * @type {ExponentialBackoffRetry}\r\n */\r\nlet exponentialBackoffRetry: ExponentialBackoffRetry;\r\n\r\n/**\r\n * Number of times to retry requests\r\n */\r\nconst retryCount: number = 3;\r\n\r\n/**\r\n * Sends a request\r\n *\r\n * @returns {Promise} - A promise to fulfill the request\r\n */\r\nexport async function sendRequest(request: () => Promise, activityName: string): Promise {\r\n const activity = getInstrumentationService().activityLoggingService.createActivity(activityName);\r\n\r\n return await OneServiceUtility.serviceRequestOnComplete(\r\n () => getExponentialBackoffRetry().executeRequest(request, null, activity),\r\n () => getInstrumentationService().activityLoggingService.endActivity(activity));\r\n}\r\n\r\n/**\r\n * Get exponential backoff retry instance\r\n */\r\nfunction getExponentialBackoffRetry(): ExponentialBackoffRetry {\r\n if (exponentialBackoffRetry) {\r\n return exponentialBackoffRetry;\r\n }\r\n\r\n exponentialBackoffRetry = new ExponentialBackoffRetry(getInstrumentationService().loggingService, retryCount);\r\n\r\n return exponentialBackoffRetry;\r\n}\r\n\r\n/**\r\n * Get instrumentation service instance\r\n */\r\nfunction getInstrumentationService(): IInstrumentationService {\r\n if (instrumentationService) {\r\n return instrumentationService;\r\n }\r\n\r\n const activityService = ActivityLoggingService.getInstance(\"ExperienceActivityLogger\");\r\n // Todo: use a different appender to log into mds tables\r\n if (logger.isDebug()) {\r\n activityService.addAppender(new BrowserConsoleAppender(LogLevel.Activity));\r\n }\r\n\r\n instrumentationService = new InstrumentationService(logger.getLoggingService(), activityService);\r\n\r\n return instrumentationService;\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { BreakpointManager, BreakpointManagerCallback, ColumnArrangement, columnArrangements } from \"./BreakpointManager\";\r\nimport { BreakpointTracker, BreakpointTrackerCallback, defaultBreakpoints, identifyBreakpoint } from \"@microsoft/fast-layouts-react\";\r\n\r\nimport { Breakpoint } from \"@microsoft/fast-layouts-react\";\r\nimport { pull as _pull } from \"lodash-es\";\r\n\r\n/**\r\n * This class establishes a standard breakpoint scheme that can be used by all experiences\r\n * to achieve a unified breakpoint strategy. The implementation is a glorified wrapper around\r\n * the FAST BreakpointTracker that standardizes on a set of specific number of column arrangements\r\n * that will then be exposed to clients via the {ColumnArrangement} enum.\r\n */\r\nexport class FastBreakpointManager implements BreakpointManager {\r\n\r\n /**\r\n * Map of BreakpointManager callbacks to Breakpoint Tracker callback.\r\n * Required to quickly get Breakpoint callback on unsubscribe.\r\n */\r\n private callbackMap: Map = new Map();\r\n\r\n /**\r\n * Gets the {ColumnArrangement} enum that maps to the current viewport width.\r\n */\r\n public get currentColumnArrangement(): ColumnArrangement {\r\n return this.indexToStandardConverter(BreakpointTracker.currentBreakpoint());\r\n }\r\n\r\n /**\r\n * The constructor\r\n */\r\n public constructor(width?: number) {\r\n this.refreshBreakpoints();\r\n\r\n if (width !== null) {\r\n BreakpointTracker.defaultBreakpoint = identifyBreakpoint(width, BreakpointTracker.breakpoints);\r\n }\r\n }\r\n\r\n /**\r\n * Reinitialize the FastBreakpointManager. Useful when handling multiple requests when server side rendering.\r\n */\r\n public static reinitialize(width?: number): void {\r\n fastBreakpointManager = new FastBreakpointManager(width);\r\n }\r\n\r\n /**\r\n * Refreshes breakpoints from current column arrangements.\r\n */\r\n public refreshBreakpoints(): void {\r\n const breakpoints: number[] = [0];\r\n for (let i = 1; i < columnArrangements.length; i++) {\r\n breakpoints.push(columnArrangements[i].minViewportWidthPx);\r\n }\r\n\r\n this.breakpoints = breakpoints;\r\n }\r\n\r\n /** breakpoint values */\r\n public set breakpoints(breakpoints: number[]) {\r\n BreakpointTracker.breakpoints = breakpoints;\r\n\r\n // TODO: Remove this when https://github.com/microsoft/fast-dna/issues/2602 is solved\r\n if (defaultBreakpoints && Array.isArray(defaultBreakpoints)) {\r\n const count = defaultBreakpoints.length;\r\n for (let i = 0; i < count; i++) {\r\n defaultBreakpoints.pop();\r\n }\r\n breakpoints.forEach(breakpoint => defaultBreakpoints.push(breakpoint));\r\n }\r\n\r\n // TODO: Remove after Fix of BreakpointTracker which update current breakpoint on setting breakpoint list.\r\n BreakpointTracker.update();\r\n }\r\n\r\n public get breakpoints(): number[] {\r\n return BreakpointTracker.breakpoints;\r\n }\r\n\r\n /**\r\n * Add a subscription to the breakpoint tracker changed notification list\r\n * @param callback - the callback to invoke when the breakpoint changes\r\n */\r\n public subscribe(callback: BreakpointManagerCallback): void {\r\n\r\n // Create callback with breakpoint value conversion.\r\n const managerCallback = (breakpoint: Breakpoint) => {\r\n callback(this.indexToStandardConverter(breakpoint));\r\n };\r\n\r\n this.callbackMap.set(callback, managerCallback);\r\n\r\n BreakpointTracker.subscribe(managerCallback);\r\n }\r\n\r\n /**\r\n * Removes an existing subscription from the breakpoint tracker notification list\r\n * @param callback - the callback to remove from the notification list\r\n */\r\n public unsubscribe(callback: BreakpointManagerCallback): void {\r\n BreakpointTracker.unsubscribe(this.callbackMap.get(callback));\r\n this.callbackMap.delete(callback);\r\n }\r\n\r\n /**\r\n * Converts an index-based breakpoint to a column arrangement.\r\n * @param breakpoint The breakpoint index to convert.\r\n * @returns The corresponding column arrangement.\r\n */\r\n private indexToStandardConverter(breakpoint: Breakpoint): ColumnArrangement {\r\n return columnArrangements[breakpoint].arrangement;\r\n }\r\n}\r\n\r\n/** Default exported instance of the {BreakpointManager} */\r\nexport let fastBreakpointManager = new FastBreakpointManager();\r\n\r\n/** Reset the fast breakpoint manager. Useful for tests and server side rendering. */\r\nexport let resetFastBreakpointManager = (width?: number) => FastBreakpointManager.reinitialize(width);","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { getAppEnvironment, getHeadData } from \"@msnews/core\";\r\nimport { useEnterpriseCompliance, useEnterpriseDomain } from \"@msnews/auth\";\r\n\r\nimport { logger } from \"@msnews/diagnostics\";\r\n\r\n/**\r\n * The service URL to use\r\n */\r\nlet serviceUrl: URL;\r\n\r\n/**\r\n * The feed service URL to use\r\n */\r\nlet feedServiceUrl: URL;\r\n\r\n/**\r\n * Initialize AppServiceManager with serviceUrl\r\n *\r\n * @param url {string} - The service url\r\n */\r\nexport function initializeServiceRequest(url: URL): void {\r\n serviceUrl = new URL(\"\", url);\r\n initializationLogs(serviceUrl);\r\n}\r\n\r\n/**\r\n * Initialize AppServiceManager with feedServiceUrl\r\n *\r\n * @param url {string} - The feed service url\r\n */\r\nexport function initializeFeedServiceRequest(url: URL): void {\r\n feedServiceUrl = new URL(\"\", url);\r\n initializationLogs(feedServiceUrl);\r\n}\r\n\r\n/**\r\n * Returns service url\r\n * @returns an URL pointing to Service Request base URL\r\n */\r\nexport function getServiceUrl(): URL {\r\n const appEnvironment = getAppEnvironment();\r\n\r\n if (!serviceUrl) {\r\n // Use enterprise request if in enterprise compliant scenario\r\n const isEnterpriseDomain = useEnterpriseCompliance() && useEnterpriseDomain();\r\n const url = isEnterpriseDomain ? appEnvironment.EnterpriseServiceUrlBase : appEnvironment.ServiceUrlBase;\r\n\r\n initializeServiceRequest(url);\r\n }\r\n\r\n return serviceUrl;\r\n}\r\n\r\n/**\r\n * Returns feed service url\r\n * @returns an URL pointing to Feed Service Request base URL\r\n */\r\nexport function getFeedServiceUrl(): URL {\r\n const appEnvironment = getAppEnvironment();\r\n\r\n if (!feedServiceUrl) {\r\n // Use enterprise request if in enterprise compliant scenario\r\n const isEnterpriseDomain = useEnterpriseCompliance() && useEnterpriseDomain();\r\n const url = isEnterpriseDomain ? appEnvironment.EnterpriseServiceUrlBase : appEnvironment.FeedServiceUrlBase;\r\n\r\n initializeFeedServiceRequest(url);\r\n }\r\n\r\n return feedServiceUrl;\r\n}\r\n\r\n/**\r\n * Appends `subPath` to Service Request URL.\r\n * It is an abstraction for the client so it won't have to\r\n * know the url format\r\n * @param subPath the path to append to Service Request URL\r\n * @returns an URL pointing to Service Request base URL appended by `subPath`\r\n */\r\nexport function getServiceUrlForSubpath(subPath: string): URL {\r\n return new URL(subPath + getServiceUrl().search, getServiceUrl());\r\n}\r\n\r\n/**\r\n * Appends `subPath` to Feed Service Request URL.\r\n * It is an abstraction for the client so it won't have to\r\n * know the url format\r\n * @param subPath the path to append to Feed Service Request URL\r\n * @returns an URL pointing to Feed Service Request base URL appended by `subPath`\r\n */\r\nexport function getFeedServiceUrlForSubpath(subPath: string): URL {\r\n return new URL(subPath + getFeedServiceUrl().search, getFeedServiceUrl());\r\n}\r\n\r\n/**\r\n * Add initial logs based on url and environment\r\n * @param url the url that is being used to initialize\r\n */\r\nfunction initializationLogs(url: URL): void {\r\n let authEnabled: boolean = false;\r\n if (!process.env.WEBPACK_DEV_SERVER && url.searchParams.get(\"env.service\") !== \"dev\" && getHeadData().UserIsSignedIn) {\r\n authEnabled = true;\r\n }\r\n\r\n logger.log(\"u-si: \" + getAppEnvironment().UserId);\r\n logger.log(\"a-si: \" + authEnabled);\r\n logger.log(\"ss-si: \" + getHeadData().UserIsSignedIn);\r\n}","\r\n// © Microsoft Corporation. All rights reserved.\r\n\r\n// TODO: This should be considered for moving it to the Interests experience wrapper, once that\r\n// code arrives, since this is specific to that experience\r\n\r\nimport { SubnavTabId } from \"./SubnavTabId\";\r\nimport { SubnavTabName } from \"./SubnavTabName\";\r\n\r\nexport namespace TabsHelper {\r\n /**\r\n * Converts from the tab enum to the tab names\r\n *\r\n * @export\r\n * @param {SubnavTabId} tabId - The tabId being converted\r\n * @return The tab name\r\n */\r\n export function tabIdToTabName(tabId: SubnavTabId): string {\r\n switch (tabId) {\r\n case SubnavTabId.Interests:\r\n return SubnavTabName.Interests;\r\n\r\n case SubnavTabId.MyFeed:\r\n return SubnavTabName.MyFeed;\r\n\r\n case SubnavTabId.XFeed:\r\n return SubnavTabName.XFeed;\r\n\r\n default:\r\n return \"\";\r\n }\r\n }\r\n\r\n /**\r\n * Converts from the tab name to the tab enum\r\n *\r\n * @export\r\n * @param {string} tabName - The tabName being converted\r\n * @return The tabId\r\n */\r\n export function tabNameToTabId(tabName: string): SubnavTabId {\r\n switch (tabName) {\r\n\r\n case SubnavTabName.MyFeed:\r\n return SubnavTabId.MyFeed;\r\n\r\n case SubnavTabName.XFeed:\r\n return SubnavTabId.XFeed;\r\n\r\n case SubnavTabName.Interests:\r\n return SubnavTabId.Interests;\r\n\r\n default:\r\n return SubnavTabId.None;\r\n }\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nexport namespace DynamicBundles {\r\n const dynamicBundles: { [experienceName: string]: () => Promise } = {};\r\n\r\n /**\r\n * lazy load the experience\r\n *\r\n * @param experienceName - the experience name\r\n * @return {Promise} - the experience wrapped by the promise\r\n */\r\n export const loadExperience = async (experienceName: string) => {\r\n const bundle = dynamicBundles[experienceName];\r\n if (!bundle) {\r\n throw new Error(`Attempted to load unknown dynamic bundle \"${experienceName}\". Make sure it's a registered dynamic experience bundle.`);\r\n }\r\n return bundle();\r\n }\r\n\r\n /**\r\n * register the experience for lazy loading\r\n *\r\n * @param experienceName - the experience name\r\n * @param es6Import - the import(\"@msnews/your/experience/path\")\r\n */\r\n export const registerExperience = (experienceName: string, es6Import: () => Promise) => {\r\n dynamicBundles[experienceName] = es6Import;\r\n };\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Prefix that all flights for peregrine will use\r\n */\r\nconst peregrineFlightPrefix: string = \"prg-\";\r\n\r\n/**\r\n * Goes through the array of flights that is given and will filter out any flight that doesn't start with\r\n * prg-. It then sorts them and returns a new string[].\r\n * @param flights Array of flights that we will filter through and return only the peregrine\r\n * specific flights\r\n */\r\nexport function getPeregrineFlights(flights: string[]): string[] {\r\n if (!flights || flights.length === 0) {\r\n return flights;\r\n }\r\n\r\n let cleanedUpFlights = [];\r\n flights.forEach((item) => {\r\n let lowercaseItem = item.toLocaleLowerCase();\r\n if (lowercaseItem.startsWith(peregrineFlightPrefix)) {\r\n cleanedUpFlights.push(lowercaseItem);\r\n }\r\n });\r\n\r\n return cleanedUpFlights.sort();\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { AppError, PerfTimeline, ResolverAppErrors, logger, tryGetPerfTimeline } from \"@msnews/diagnostics\";\r\nimport { Environment, PageRequestTargetScope, appEnvironment } from \"../app\";\r\nimport { ExperienceConfigWrapper, ExperienceConfigs } from \"./configs/\";\r\nimport { IndexedDb, UrlUtility, Utility, getFromWebWorker, isWebWorkerPresent, localStorage, sendToWebWorker, ServerCache } from \"../utilities\";\r\nimport { getLocationHref, getLocationSearch, canUseDOM, getRequestData } from \"@msnews/isomorphic-util\";\r\nimport { isArray, isEmpty, isString, memoize, mergeWith } from \"lodash-es\";\r\n\r\nimport { IExperienceConfig } from \"cms-models-msn/configuration/IExperienceConfig\";\r\nimport { IExperienceConfigIndex } from \"cms-models-msn/configuration/IExperienceConfigIndex\";\r\nimport { IExperienceConfigLink } from \"cms-models-msn/configuration/IExperienceConfigLink\";\r\nimport { getPeregrineFlights } from \"@msnews/experimentation-helpers\";\r\n\r\n/**\r\n * Type definition for cached configs in the indexed DB\r\n */\r\ntype CachedConfigsType = Map;\r\n\r\n/**\r\n * Constants for TTLs\r\n */\r\nconst SERVER_CACHE_TTL: number = 60 * 60 * 24 * 1000; // one day in milliseconds\r\nconst SERVER_CACHE_CONFIG_STALENESS_TIMEOUT: number = 5 * 60 * 1000; // 5 minutes in milliseconds\r\n\r\n/**\r\n * Resolver Class\r\n */\r\nclass Resolver {\r\n\r\n /**\r\n * The single instance of the Resolver class.\r\n * @type {Resolver}\r\n */\r\n private static _instance: Resolver = null;\r\n\r\n /**\r\n * Target scope of the current page request\r\n * @type {PageRequestTargetScope}\r\n */\r\n private currentTargetScope: PageRequestTargetScope = appEnvironment.CurrentRequestTargetScope;\r\n\r\n /**\r\n * Dictionary to maintain all resolved config for internal state management\r\n * @type {Map}\r\n */\r\n private configMap: CachedConfigsType = new Map();\r\n\r\n /** set fallback env to prod to avoid any live site issues */\r\n private env: Environment = appEnvironment.Environment || Environment.prod;\r\n\r\n /**\r\n * Config base url used during cms config resolution.\r\n * @type {string}\r\n */\r\n private cdnConfigBaseUrl: URL;\r\n\r\n /**\r\n * Config base url for Config Service\r\n * @type {string}\r\n */\r\n private configServiceBaseUrl: URL;\r\n\r\n /**\r\n * Dictionary to maintain all promise objects which are not resolved/rejected. Once promise object is resolved/rejected,\r\n * it gets deleted from this dictionary and put in the configMap.\r\n * @type {Map>}\r\n */\r\n private promiseMap: Map> = new Map();\r\n\r\n /** Resolver app errors */\r\n private resolverErrors: AppError[];\r\n\r\n /** Object of IndexedDb wrapper class */\r\n private indexedDb: IndexedDb;\r\n\r\n /* Check if IndexedDb operation is allowed or not.\r\n * @type {boolean}\r\n */\r\n private useIndexedDb: boolean;\r\n\r\n /* Check if ServerCache can be used or not.\r\n * @type {boolean}\r\n */\r\n private useServerCache: boolean;\r\n\r\n /** Current Timestamp for config staleness check. */\r\n private stalenessCheckTimestamp: number = new Date().getTime();\r\n\r\n /* Check if ConfigService operation is allowed or not.\r\n * @type {boolean}\r\n */\r\n private enableConfigService: boolean;\r\n\r\n /* Get config service parameters from currentTargetScope\r\n * @type {string}\r\n */\r\n private configServiceParameters: string;\r\n\r\n /* Storage key for indexedDb\r\n * @type {string}\r\n */\r\n private storageKey: string;\r\n\r\n /** Config timings object storing fetch duration of network or cache to retrieve config. */\r\n private configTimings: ConfigFetchTiming[];\r\n\r\n /**\r\n * Check if web worker exists\r\n * @type {boolean}\r\n */\r\n private useWebWorkerToCache: boolean;\r\n\r\n /** The perf timeline for the resolver */\r\n private perfTimeline: PerfTimeline = tryGetPerfTimeline(\"Resolver\", \"Resolver\", true);\r\n\r\n /**\r\n * Check if config service shold return more than 1 config\r\n * @type {boolean}\r\n */\r\n private isMultiConfigRetrievalEnabled = false;\r\n\r\n /** Initialize indexedDb for configs. */\r\n private initializeIndexedDb = memoize(this._initializeIndexedDb);\r\n\r\n /** Initialize configs from IDB. */\r\n private populateConfigMapFromIndexedDbAsync = memoize(this._populateConfigMapFromIndexedDbAsync);\r\n\r\n /**\r\n * Constructor to initialize private variables.\r\n */\r\n public constructor() {\r\n this.initializeCaching();\r\n }\r\n\r\n /**\r\n * Initialize caching layer of resolver.\r\n *\r\n * WARNING!!! Do NOT add async/await in this function. It must remain a pure synchronous function in order\r\n * to initialize the indexedDB cache as quickly as possible before entry point beats to us due to multi-level\r\n * promise waiting hierarchies.\r\n *\r\n * @param idb object of indexedDb class. Unit tests set this value. It will be null in other cases.\r\n * @\r\n */\r\n public initializeCaching(idb?: IndexedDb): void {\r\n /**\r\n * In most cases configRootUrl will be sent by PCS so appEnvironment will have it.\r\n * In case it is not sent, we fall back to environmentConfig so config will be always served.\r\n */\r\n this.cdnConfigBaseUrl = appEnvironment.ConfigRootUrl || appEnvironment.EnvironmentConfigUrl;\r\n\r\n // Get ConfigServiceBaseUrl from appEnvironment\r\n this.configServiceBaseUrl = appEnvironment.ConfigServiceBaseUrl;\r\n\r\n this.resolverErrors = [];\r\n this.configTimings = [];\r\n\r\n this.useWebWorkerToCache = isWebWorkerPresent;\r\n\r\n this.perfTimeline = tryGetPerfTimeline(\"Resolver\", \"Resolver\");\r\n\r\n this.indexedDb = idb ? idb : new IndexedDb();\r\n\r\n // Check if IndexedDb is supported\r\n this.useIndexedDb =\r\n // Debug scenario: Check if indexedDB is allowed to be read in main thread. By default true.\r\n this.enableIndexedDbInMainResolver()\r\n // PCS flag to turn on/off IndexedDb caching of configs.\r\n && !appEnvironment.DisableCachingConfigs\r\n // Debug scenario: to turn off indexedDB in all threads.\r\n && this.indexedDb.isCachingAllowed\r\n // Check if there exists IndexedDB in browser\r\n && this.indexedDb.supported;\r\n\r\n // Check if server cache could be used or not\r\n this.useServerCache = ServerCache !== null\r\n // PCS flag to turn on/off IndexedDb caching of configs.\r\n && !appEnvironment.DisableCachingConfigs;\r\n\r\n // Check whether to use Config Resolver Service (CRS).\r\n this.enableConfigService = this.useConfigService();\r\n if (this.enableConfigService) {\r\n const scopeWithPeregrineFlights = { ...this.currentTargetScope,\r\n pageExperiments: getPeregrineFlights(this.currentTargetScope.pageExperiments) };\r\n\r\n // Query string parameter from target scope.\r\n this.configServiceParameters = \"?targetScope=\" + JSON.stringify(scopeWithPeregrineFlights);\r\n\r\n // Send PCS apptype to CRS so we can build CRS Jarvis dashboards per apptype.\r\n this.configServiceParameters += `&apptype=${appEnvironment.AppType}`;\r\n\r\n const { IsMultiConfigRetrievalEnabled, CacheBustingIdentifier } = appEnvironment;\r\n\r\n // Check if CRS should fetch multiple configs and its depth.\r\n this.isMultiConfigRetrievalEnabled = IsMultiConfigRetrievalEnabled;\r\n if (this.isMultiConfigRetrievalEnabled) {\r\n this.configServiceParameters += `&maxDepth=${this.getConfigRetrievalMaxDepth()}`;\r\n }\r\n\r\n // Send cache busting identifier to CRS, if sent by PCS.\r\n if (CacheBustingIdentifier) {\r\n this.configServiceParameters += `&cbid=${CacheBustingIdentifier}`;\r\n }\r\n\r\n // If url has dev only query string params, inform CRS so it can exclude from availability and will help debugging on Jarvis.\r\n if (this.containsDevOnlyQueryParameters()) {\r\n this.configServiceParameters += \"&item=dev:true\";\r\n }\r\n }\r\n\r\n // Get storage key based on target scope.\r\n this.storageKey = this.generateKey();\r\n\r\n // if pre-initialized config map doesn't exist or does not contain the storageKey entry we want,\r\n // then proceed to asynchronously initialize the configMap from indexedDb\r\n // NOTE: we only start the async read, and don't await for this to finish\r\n this.populateConfigMapFromIndexedDbAsync();\r\n }\r\n\r\n /**\r\n * Merges config objects.\r\n * @private\r\n * @param {ExperienceConfigWrapper[]} configs - an array of config documents\r\n * @param {string} experienceType - experienceType\r\n * @return ExperienceConfig - returns merged config based on a set of rules\r\n */\r\n public mergeConfig(configs: IExperienceConfig[]): IExperienceConfig {\r\n if (!configs || configs.length < 1) {\r\n return null;\r\n }\r\n\r\n let result: IExperienceConfig = configs[0];\r\n\r\n // skip the 0th item as it is assigned to result above, only merge properties section\r\n for (let count = 1; count < configs.length; count++) {\r\n result.properties = mergeWith(result.properties, configs[count].properties, this.customizer);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * matches targeting scope and returns the config urls for the same.\r\n * @private\r\n * @param {IExperienceConfigIndex} configIndex - an array of config documents\r\n * @return string[] - returns urls for configurations for which the scope matched\r\n */\r\n public resolveConfigIndex(configIndex: IExperienceConfigIndex): string[] {\r\n if (!configIndex) {\r\n return null;\r\n }\r\n\r\n let configPaths: string[] = [];\r\n configIndex.configs.forEach(experienceRef => {\r\n if (this.targetScopeMatched(experienceRef)) {\r\n configPaths.push(experienceRef.href);\r\n }\r\n });\r\n\r\n // if override config is provided, then we add that to the end of list\r\n // so props provided in override config will add/update existing properties.\r\n // This is similar to CMS override settings but scoped to experience level.\r\n if (configIndex.overrideConfig && Utility.stringHasData(configIndex.overrideConfig.href)) {\r\n configPaths.push(configIndex.overrideConfig.href);\r\n }\r\n\r\n return configPaths;\r\n }\r\n\r\n /**\r\n * basic version of target scope that only checks market currently.\r\n * @private\r\n * @param {IExperienceConfigReference} experienceRef - experience config reference that has targetscope as child property\r\n * @return boolean - true if current target scope matches with config target scope, otherwise false\r\n */\r\n public targetScopeMatched(experienceRef: IExperienceConfigLink): boolean {\r\n const targetScope = experienceRef.targetScope;\r\n\r\n // if target scope is undefined for a config entry, we treat that as default config and apply it\r\n if (!targetScope) {\r\n return true;\r\n }\r\n\r\n return (this.audienceModeMatched(targetScope)\r\n && this.browserTypeMatched(targetScope)\r\n && this.deviceTypeMatched(targetScope)\r\n && this.experimentMatched(targetScope)\r\n && this.marketMatched(targetScope)\r\n && this.osMatched(targetScope)\r\n && this.pageTypeMatched(targetScope)\r\n && this.platformMatched(targetScope));\r\n }\r\n\r\n /**\r\n * function to check if current audienceMode type matches target audienceMode type\r\n * @private\r\n * @param {PageRequestTargetScope} targetScope - experience config reference that has targetscope as child property\r\n * @return boolean - true if current target scope audienceMode matches with config target scope audienceMode, otherwise false\r\n */\r\n public audienceModeMatched(targetScope: PageRequestTargetScope): boolean {\r\n return !targetScope.audienceMode || this.currentTargetScope.audienceMode === targetScope.audienceMode;\r\n }\r\n\r\n /**\r\n * function to check if current browser type matches target browser type\r\n * @private\r\n * @param {PageRequestTargetScope} targetScope - experience config reference that has targetscope as child property\r\n * @return boolean - true if current target scope browser type matches with config target scope browser type, otherwise false\r\n */\r\n public browserTypeMatched(targetScope: PageRequestTargetScope): boolean {\r\n if (!targetScope.browser || !targetScope.browser.browserType) {\r\n return true;\r\n }\r\n\r\n if (this.currentTargetScope.browser && this.currentTargetScope.browser.browserType === targetScope.browser.browserType &&\r\n (!targetScope.browser.version || this.currentTargetScope.browser.version === targetScope.browser.version)) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * function to check if current device type matches target device type\r\n * @private\r\n * @param {PageRequestTargetScope} targetScope - experience config reference that has targetscope as child property\r\n * @return boolean - true if current target scope device type matches with config target scope device type, otherwise false\r\n */\r\n public deviceTypeMatched(targetScope: PageRequestTargetScope): boolean {\r\n return !targetScope.deviceFormFactor || this.currentTargetScope.deviceFormFactor === targetScope.deviceFormFactor;\r\n }\r\n\r\n /**\r\n * function to check if current experiment id matches with the requested scope experiment id.\r\n * @private\r\n * @param {PageRequestTargetScope} targetScope - experience config reference that has targetscope as child property\r\n * @return boolean - true if current target scope experiment matches with config target scope experiment, otherwise false\r\n */\r\n public experimentMatched(targetScope: PageRequestTargetScope): boolean {\r\n this.currentTargetScope.pageExperiments = this.currentTargetScope.pageExperiments || [];\r\n\r\n if (!isString(targetScope.experimentId) || isEmpty(targetScope.experimentId)\r\n || this.currentTargetScope.pageExperiments.indexOf(targetScope.experimentId) >= 0) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Compare the strings case insensitive.\r\n * @private\r\n * @param {string} lhs The string to compare.\r\n * @param {string} rhs The string to compare against.\r\n * @return {number} - true if the strings equal case insensitive.\r\n */\r\n public stringsEqualCaseInsensitive(lhs: string, rhs: string): boolean {\r\n return (lhs || \"\").localeCompare(rhs || \"\", undefined, { sensitivity: \"accent\" }) === 0;\r\n }\r\n\r\n /**\r\n * function to check if current market scope match with target scope market.\r\n * @private\r\n * @param {PageRequestTargetScope} targetScope - experience config reference that has targetscope as child property\r\n * @return boolean - true if current target scope market matches with config target scope market, otherwise false\r\n */\r\n public marketMatched(targetScope: PageRequestTargetScope): boolean {\r\n // if locale is not part of target scope, we assume it is applicable for all locale.\r\n // Separated out this if condition to have clarity about this behavior.\r\n if (!targetScope.locale) {\r\n return true;\r\n }\r\n\r\n const targetLocale = targetScope.locale;\r\n const currentLocale = this.currentTargetScope.locale;\r\n\r\n if ((!targetLocale.language || this.stringsEqualCaseInsensitive(targetLocale.language, currentLocale.language)) &&\r\n (!targetLocale.market || this.stringsEqualCaseInsensitive(targetLocale.market, currentLocale.market)) &&\r\n (!targetLocale.script || this.stringsEqualCaseInsensitive(targetLocale.script, currentLocale.script))) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * function to check if current operating system type matches target operating system type\r\n * @private\r\n * @param {PageRequestTargetScope} targetScope - experience config reference that has targetscope as child property\r\n * @return boolean - true if current target scope operating system type matches with config target scope operating system type, otherwise false\r\n */\r\n public osMatched(targetScope: PageRequestTargetScope): boolean {\r\n return !targetScope.os || this.currentTargetScope.os === targetScope.os;\r\n }\r\n\r\n /**\r\n * function to check if current pagetype matches target scope\r\n * @private\r\n * @param {PageRequestTargetScope} targetScope - experience config reference that has targetscope as child property\r\n * @return boolean - true if current target scope pagetype matches with config target scope pagetype, otherwise false\r\n */\r\n public pageTypeMatched(targetScope: PageRequestTargetScope): boolean {\r\n return !targetScope.pageType || this.currentTargetScope.pageType === targetScope.pageType;\r\n }\r\n\r\n /**\r\n * function to check if current scope platform type matches target scope platform type\r\n * @private\r\n * @param {PageRequestTargetScope} targetScope - experience config reference that has targetscope as child property\r\n * @return boolean - true if current target scope platform matches with config target scope platform, otherwise false\r\n */\r\n public platformMatched(targetScope: PageRequestTargetScope): boolean {\r\n return !targetScope.platform || this.currentTargetScope.platform === targetScope.platform;\r\n }\r\n\r\n /**\r\n * Customizer for merge. We are explcitly overriding the array from taget to source. No array elements from source are preserved.\r\n * @private\r\n * @param {any} srcValue - source object to merge. Can be of type any\r\n * @param {any} objValue - target object to merge. Can be of type any\r\n * @return target Object when the type is array. Otherwise uses default behavior of merge.\r\n */\r\n public customizer(srcValue: any, objValue: any): any {\r\n if (isArray(srcValue)) {\r\n return objValue;\r\n }\r\n }\r\n\r\n /**\r\n * Function to clear internal state map for Unit testing.\r\n * @public\r\n * @void\r\n */\r\n public clearInternalState(): void {\r\n this.configMap.clear();\r\n this.initializeIndexedDb.cache.clear();\r\n this.populateConfigMapFromIndexedDbAsync.cache.clear();\r\n }\r\n\r\n /**\r\n * Function to override current request target scope. Should be used only when running outside the\r\n * context of client side rendering. Example tooling.\r\n * This function should not be called by any client rendering experience running inside the Page Context.\r\n * @public\r\n * @param {PageRequestTargetScope} targetScope - Target scope to override current Request target scope\r\n * @void\r\n */\r\n public overrideCurrentRequestTargetScope(targetScope: PageRequestTargetScope): void {\r\n this.currentTargetScope = targetScope;\r\n }\r\n\r\n /**\r\n * Function to override current request environment. Should be used only when not running outside the\r\n * context of client side rendering. Example tooling\r\n * @public\r\n * @param {Environment} overrideEnv - environment enum to override\r\n * @void\r\n */\r\n public overrideCurrentRequestEnvironment(overrideEnv: Environment): void {\r\n // fallback as prod\r\n this.env = overrideEnv || Environment.prod;\r\n }\r\n\r\n /**\r\n * Overrides a config entry. Use for local testing only. Does not work on PROD environment.\r\n * @param relativeUrl The config index URL to override\r\n * @param experienceType The experience type\r\n * @param config The config to use\r\n */\r\n public async overrideConfig(relativeUrl: string, experienceType: string, config: any): Promise {\r\n if (this.env !== Environment.prod) {\r\n await this.addConfigToConfigMap(\r\n relativeUrl,\r\n {\r\n experienceType: experienceType,\r\n properties: config,\r\n typeVersion: \"1.0.0\",\r\n _name: \"index\"\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Returns the resolved merged Experience config when passed Experience Config Index.\r\n * This function downloads the config index, filter based on target scope, download the configs and\r\n * merge the configs\r\n * @public\r\n * @param {string} relativeUrl - Expeience Index document relative url\r\n * @return Promise\r\n */\r\n public async getConfig(relativeUrl: string): Promise {\r\n\r\n let cacheKey = this.getCacheKey(relativeUrl);\r\n\r\n if (!this.currentTargetScope || !relativeUrl || !isString(relativeUrl) || isEmpty(relativeUrl)) {\r\n throw new Error(\"getConfig: Invalid target scope or relativeUrl\");\r\n }\r\n\r\n const startGetConfig = performance.now();\r\n\r\n // if it exists in memory, return it immediately\r\n const configFromMemory = this.configMap.get(cacheKey);\r\n if (configFromMemory) {\r\n this.addConfigTiming(configFromMemory.experienceType, startGetConfig, \"cache\");\r\n return configFromMemory;\r\n }\r\n\r\n // if promiseMap has the item, we already have an active promise which is not yet resolved/rejected. Return this promise\r\n const existingPromise = this.promiseMap.get(cacheKey);\r\n if (existingPromise) {\r\n return existingPromise;\r\n }\r\n\r\n let processed = false;\r\n const configEndMeasure = this.perfTimeline && this.perfTimeline.startMeasure(\"config\", relativeUrl).endMeasure;\r\n let experienceType: string;\r\n let configSource: string;\r\n\r\n let configPromise = new Promise(async (resolve, reject) => {\r\n\r\n try {\r\n // Fetch merged config from server cache if available\r\n if (this.useServerCache) {\r\n const cachedOnServer: boolean = await ServerCache.has(cacheKey);\r\n if (cachedOnServer) {\r\n // Retrieve and deserialize the stringified config stored in ServerCache\r\n const serializedConfig: string = await ServerCache.get(cacheKey);\r\n const configFromServerCache = JSON.parse(serializedConfig) as ExperienceConfigWrapper;\r\n if (configFromServerCache) {\r\n this.configTimings.push({\r\n experienceType: configFromServerCache.experienceType,\r\n cacheFetchDuration: performance.now() - startGetConfig\r\n });\r\n processed = true;\r\n this.promiseMap.delete(cacheKey);\r\n resolve(configFromServerCache);\r\n\r\n // Invalidate config in server cache if this is already stale (5 minutes)\r\n //\r\n // Might prefer to actively refresh in a separate worker instead on server hot path.\r\n //\r\n // TODO Tracking Work Item: Investigate refresh config in server cache\r\n // https://dev.azure.com/microsoft/OS/_workitems/edit/24737222\r\n if (this.isServerCacheConfigStale(configFromServerCache.storageTimestamp)) {\r\n ServerCache.del(cacheKey);\r\n }\r\n\r\n logger.log(`${this.logPrefix()} ${configFromServerCache.experienceType} config fetched from server cache.`);\r\n return;\r\n }\r\n }\r\n\r\n // Not found on server cache so getting config from network\r\n let networkReadPromise = this.getConfigFromNetwork(relativeUrl);\r\n\r\n // Await on the network promise to get the merged config.\r\n const networkConfigsMap = await networkReadPromise;\r\n const networkConfig = networkConfigsMap.get(cacheKey);\r\n experienceType = networkConfig.experienceType;\r\n this.addConfigTiming(experienceType, startGetConfig, configSource = \"network\");\r\n resolve(networkConfig);\r\n\r\n } else {\r\n // this will contain both the IDB cache read promise, in case we haven't yet read from\r\n // IDB yet, as well as the network read promise, which we will race until one finishes.\r\n const readPromises: Array> = [\r\n\r\n // it's possible that the IDB read is still going on, so see if we can get results from\r\n // cache after racing with it. Note that we never want to 'hard await' on the IDB read\r\n // as it's possible the IDB read may have errored out / stalled, etc. So we're using this\r\n // result only as a secondary fallback. Primary is still the network.\r\n this.populateConfigMapFromIndexedDbAsync()\r\n ];\r\n\r\n let networkReadPromise = this.getConfigFromNetwork(relativeUrl);\r\n readPromises.push(networkReadPromise as Promise);\r\n\r\n // start the race between network and IDB cache read\r\n await Promise.race(readPromises);\r\n\r\n // after the race check in-memory again (in case the IDB read finished populated the\r\n // in-memory map early)\r\n const configFromMemoryAfterRace = this.configMap.get(cacheKey);\r\n if (configFromMemoryAfterRace) {\r\n experienceType = configFromMemoryAfterRace.experienceType;\r\n this.addConfigTiming(experienceType, startGetConfig, configSource = \"cache\");\r\n resolve(configFromMemoryAfterRace);\r\n return;\r\n }\r\n\r\n // Await on the network promise to get the merged config.\r\n const networkConfigsMap = await networkReadPromise;\r\n const networkConfig = networkConfigsMap.get(cacheKey);\r\n experienceType = networkConfig.experienceType;\r\n this.addConfigTiming(experienceType, startGetConfig, configSource = \"network\");\r\n resolve(networkConfig);\r\n\r\n }\r\n } catch (error) {\r\n\r\n // If we don't explicitly catch the error, then the promise never gets rejected which might cause issues during experience load time.\r\n reject(error);\r\n\r\n this.resolverErrors.push({\r\n ...ResolverAppErrors.GetConfigException,\r\n message: `Exception in getConfig for ${relativeUrl}`\r\n });\r\n } finally {\r\n\r\n processed = true;\r\n this.promiseMap.delete(cacheKey);\r\n\r\n // only measure the network operations (otherwise there are too many overlapping measures to make sense)\r\n if (configEndMeasure) {\r\n configEndMeasure(`${experienceType}-${relativeUrl}-${configSource}`);\r\n }\r\n }\r\n });\r\n\r\n // if caller is using await then this request has been processed and we should not add it to promiseMap.\r\n // if caller is trying to download multiple configs in parallel, then processed should be false.\r\n if (!processed) {\r\n this.promiseMap.set(cacheKey, configPromise);\r\n }\r\n\r\n return configPromise;\r\n }\r\n /**\r\n * Returns the resolved merged Experience config when passed Experience Config Index.\r\n * This function downloads the config index, filter based on target scope, download the configs and\r\n * merge the configs\r\n * @private\r\n * @param {string} relativeUrl - Expeience Index document relative url.\r\n * @return Promise> map of config(s) resolved by service/cdn.\r\n */\r\n public async getConfigFromNetwork(relativeUrl: string): Promise> {\r\n\r\n let cacheKey = this.getCacheKey(relativeUrl);\r\n\r\n let mergedConfigsMap = new Map();\r\n\r\n if (this.enableConfigService) {\r\n try {\r\n const configServiceRelativeUrl = this.removeCmsPathFromRelativeUrl(relativeUrl) + this.configServiceParameters;\r\n\r\n // Get merged config from config service with multi config support.\r\n if (this.isMultiConfigRetrievalEnabled) {\r\n const crsResponse = await this.downloadFile(new URL(`${configServiceRelativeUrl}${this.configServiceBaseUrl.search}`, this.configServiceBaseUrl));\r\n if (crsResponse && crsResponse.rootConfigIndexId && crsResponse.configs) {\r\n for (const crsMergedConfig of Object.values(crsResponse.configs)) {\r\n if (crsMergedConfig && crsMergedConfig.configIndexHref) {\r\n const configIndexKey = crsMergedConfig.configIndexHref;\r\n // Save config to in-memory cache\r\n await this.addConfigToConfigMap(configIndexKey, crsMergedConfig);\r\n mergedConfigsMap.set(this.getCacheKey(configIndexKey), crsMergedConfig);\r\n logger.log(`${this.logPrefix()} ${configIndexKey} config for ${crsMergedConfig.experienceType} fetched from network using CRS url with multi config support.`);\r\n }\r\n }\r\n\r\n return mergedConfigsMap;\r\n }\r\n }\r\n\r\n // Get single merged config from config service\r\n const crsConfig = await this.downloadFile(new URL(`${configServiceRelativeUrl}${this.configServiceBaseUrl.search}`, this.configServiceBaseUrl));\r\n\r\n // Save config to in-memory cache\r\n await this.addConfigToConfigMap(relativeUrl, crsConfig);\r\n mergedConfigsMap.set(cacheKey, crsConfig);\r\n logger.log(`${this.logPrefix()} ${cacheKey} config for ${crsConfig.experienceType} fetched from network using CRS url.`);\r\n return mergedConfigsMap;\r\n\r\n } catch (error) {\r\n this.resolverErrors.push({\r\n ...ResolverAppErrors.CrsFetchFailed,\r\n message: `CRS fetch failed for ${relativeUrl}. Error: ${error}`\r\n });\r\n }\r\n }\r\n\r\n // Get config from CDN when config service is not enabled or it returned null or invalid response.\r\n if (mergedConfigsMap && !mergedConfigsMap.has(cacheKey)) {\r\n const cdnConfig = await this.downloadMergeConfig(relativeUrl);\r\n if (cdnConfig) {\r\n\r\n // Save config to in-memory cache\r\n await this.addConfigToConfigMap(relativeUrl, cdnConfig);\r\n\r\n mergedConfigsMap.set(cacheKey, cdnConfig);\r\n logger.log(`${this.logPrefix()} ${cacheKey} config fetched from network using Akamai url.`);\r\n }\r\n }\r\n\r\n return mergedConfigsMap;\r\n }\r\n\r\n /**\r\n * Set configMap object with appropriate values.\r\n * @private\r\n * @param configIndexHref example: cms/api/amp/experienceConfigIndex/AfCDeG\r\n * @param config object of ExperienceConfigWrapper\r\n */\r\n public async addConfigToConfigMap(configIndexHref: string, config: ExperienceConfigWrapper): Promise {\r\n config.storageTimestamp = this.stalenessCheckTimestamp;\r\n config.configIndexHref = configIndexHref;\r\n\r\n const cacheKey = this.getCacheKey(configIndexHref);\r\n\r\n // No need to cache on configMap on server side since it will be another layer of memcache to worry about.\r\n if (this.useServerCache) {\r\n // Save config to server cache so other processes could reuse the cache.\r\n // ServerCache only accepts string to avoid serialization issues.\r\n // TTL is 1 day for now.\r\n const serializedConfig = JSON.stringify(config);\r\n await ServerCache.set(cacheKey, serializedConfig, SERVER_CACHE_TTL);\r\n } else {\r\n // Set configMap for future reference.\r\n this.configMap.set(cacheKey, config);\r\n }\r\n }\r\n\r\n /**\r\n * Clear render cache when applicable.\r\n * @private\r\n * @param areConfigsEqual: response from web worker. This is typically true or false in this case.\r\n */\r\n public purgeRenderCacheUponConfigChanges(areConfigsEqual: boolean): void {\r\n if (areConfigsEqual) {\r\n return;\r\n }\r\n\r\n try {\r\n localStorage.removeSubstringKeys(\"lastKnown_\");\r\n localStorage.removeSubstringKeys(\"timestamp_\");\r\n } catch (e) {\r\n // Send alert to monitoring system that render cache is not being purged, when it is supposed to.\r\n this.resolverErrors.push({\r\n ...ResolverAppErrors.FailedToPurgeRenderCache,\r\n message: `Failed to purge render cache when cached config and network config is not same.`\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Get the config over the network, merge and return.\r\n * @private\r\n * @param {string} relativeUrl - Expeience Index document relative url.\r\n * @return Promise\r\n */\r\n public async downloadMergeConfig(relativeUrl: string): Promise {\r\n let config: ExperienceConfigWrapper;\r\n\r\n let experienceIndex = await this.downloadFile(new URL(`${relativeUrl}${this.cdnConfigBaseUrl.search}`, this.cdnConfigBaseUrl));\r\n let configPaths = this.resolveConfigIndex(experienceIndex);\r\n const configObjects = await this.downloadExperienceConfig(this.cdnConfigBaseUrl, configPaths);\r\n config = this.mergeConfig(configObjects) as ExperienceConfigWrapper;\r\n config.experienceType = experienceIndex.experienceType;\r\n\r\n return config;\r\n }\r\n\r\n /**\r\n * Given an array of config urls, this function downloads them in parallel and returns a promise.\r\n * @private\r\n * @param {string} baseConfigUrl - base config url depends on implementation\r\n * @param {string[]} hrefs - Array of configuration relative urls\r\n * @return Promise\r\n */\r\n public async downloadExperienceConfig(baseConfigUrl: URL, hrefs: string[]): Promise {\r\n const promiseArray = [];\r\n hrefs.forEach(href => {\r\n promiseArray.push(this.downloadFile(new URL(`${href}${baseConfigUrl.search}`, baseConfigUrl)));\r\n });\r\n\r\n return await Promise.all(promiseArray);\r\n }\r\n\r\n /**\r\n * downloads file from CMS given the relative url\r\n * @private\r\n * @param {string} relativeUrl - relative url of the document\r\n * @return Promise returns generic Type object wrapped in Promise\r\n */\r\n public async downloadFile(url: URL): Promise {\r\n // Use node-fetch to be compatible with SSR\r\n return fetch(url.toString())\r\n .then(response => {\r\n if (!response.ok) {\r\n throw new Error(response.statusText);\r\n }\r\n\r\n return response.json();\r\n }, error => {\r\n throw new Error(error);\r\n });\r\n }\r\n\r\n /**\r\n * This function generates a key that is used to write/read configurations to/from storage.\r\n * example key: \"kids|ja|jp|testPage|mmx\"\r\n * @private\r\n * @return string\r\n */\r\n public generateKey(): string {\r\n\r\n // Client side resolver will use reduced set of keys for perf and retrival logic. This logic has to match WebWorkerResolver.generateKey\r\n if (canUseDOM()) {\r\n\r\n const { audienceMode = \"\", locale = {}, pageType = \"\" } = this.currentTargetScope || {};\r\n const { language, market } = locale;\r\n\r\n const keys = [audienceMode, language, market, pageType, appEnvironment.AppType || \"\"];\r\n return keys.map(key => key || \"\").join(\"|\").toLowerCase();\r\n\r\n // Server side resolver needs to generate full set of target scopes since multiple pages/users will share the same cache for longer duration\r\n } else {\r\n let { audienceMode = \"\",\r\n browser = null,\r\n deviceFormFactor = \"\",\r\n experimentId = \"\",\r\n locale = {},\r\n os = {},\r\n pageType = \"\",\r\n platform = \"\",\r\n pageExperiments = null } = this.currentTargetScope || {};\r\n const { language, market } = locale;\r\n const { browserType = \"\", version = \"\" } = browser || {};\r\n\r\n // Filter out non-peregrine flights so they are not part of cache key.\r\n pageExperiments = getPeregrineFlights(pageExperiments);\r\n\r\n const keys = [audienceMode, browserType, version, deviceFormFactor, language, market, os, experimentId, pageType, platform, pageExperiments ? pageExperiments.join() : \"\", appEnvironment.AppType || \"\"];\r\n return keys.map(key => key || \"\").join(\"|\").toLowerCase();\r\n }\r\n }\r\n\r\n /**\r\n * Function checks if ConfigService is enabled.\r\n * @returns true if supported else false.\r\n */\r\n public useConfigService(): boolean {\r\n const urlQuery = getLocationSearch();\r\n if (urlQuery) {\r\n const param = UrlUtility.getQueryParameterByName(\"enableConfigService\", urlQuery);\r\n if (param) {\r\n return param.toLocaleLowerCase() === \"true\";\r\n }\r\n }\r\n\r\n // PCS flag to turn on/off ConfigService.\r\n // When EnableConfigService = false, it gets configs from CDN and merge at client side.\r\n return appEnvironment.EnableConfigService;\r\n }\r\n\r\n /**\r\n * Function that returns maxDepth if exists in query string else default value.\r\n * This is the max depth of the config tree.\r\n * @returns Depth of config in tree.\r\n */\r\n public getConfigRetrievalMaxDepth(): number {\r\n\r\n const param = UrlUtility.getQueryParameterByName(\"maxDepth\", getLocationHref());\r\n if (param) {\r\n return parseInt(param) || 1;\r\n }\r\n\r\n // PCS flag to turn send maxDepth\r\n if (appEnvironment.FeatureFlags\r\n && appEnvironment.FeatureFlags.crsMaxDepth) {\r\n return parseInt(appEnvironment.FeatureFlags.crsMaxDepth) || 1;\r\n }\r\n\r\n // Config service to use this default to parse depth of config tree.\r\n return 1;\r\n }\r\n\r\n /**\r\n * Function checks if url has any dev only query string param\r\n * @returns true if exist else false.\r\n */\r\n public containsDevOnlyQueryParameters(): boolean {\r\n const urlQuery = getLocationSearch();\r\n const item = UrlUtility.getQueryParameterByName(\"item\", urlQuery);\r\n if (item && item.length > 0) {\r\n return true;\r\n }\r\n\r\n const segment = UrlUtility.getQueryParameterByName(\"pcsonly\", urlQuery);\r\n if (segment && segment.length > 0) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns resolver errors if any.\r\n * @returns resolverErrors\r\n */\r\n public getResolverErrors(): AppError[] {\r\n return this.resolverErrors;\r\n }\r\n\r\n /**\r\n * Refresh configs in indexedDb. Next time users visits the page within 3 days, we will get configs from indexedDB first\r\n * After TTVR we will background refresh them in web worker through this function.\r\n * If it more than 3 days, we won't use indexedDb response in main thread, After TTVR, we will background refresh.\r\n * This is required to have latest configs in indexedDb\r\n */\r\n public async refreshConfigCache(): Promise {\r\n // If web worker is not enabled, do not refresh.\r\n if (!this.useWebWorkerToCache) {\r\n return;\r\n }\r\n\r\n try {\r\n // Send post message to web worker to refresh indexedDB.\r\n const wwResponse = await getFromWebWorker({ id: \"refreshconfigs\" });\r\n if (wwResponse\r\n && wwResponse.fetched\r\n && wwResponse.payload !== undefined\r\n && wwResponse.payload !== null) {\r\n // Check if cached config and network config properties have any changes.\r\n this.purgeRenderCacheUponConfigChanges(wwResponse.payload as boolean);\r\n }\r\n } catch (e) {\r\n this.resolverErrors.push({\r\n ...ResolverAppErrors.RefreshConfigCacheFailed,\r\n message: `refreshConfigCache error. Error: ${e}`\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Function checks whether to enable or disable indexedDb in main using query string override.\r\n * @returns true if supported else false.\r\n */\r\n public enableIndexedDbInMainResolver(): boolean {\r\n const urlQuery = getLocationSearch();\r\n if (urlQuery) {\r\n const param = UrlUtility.getQueryParameterByName(\"enableIndexedDbInMainResolver\", urlQuery);\r\n if (param) {\r\n return param.toLocaleLowerCase() === \"true\";\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Function to check config is stale.\r\n * @returns true if stale else false.\r\n */\r\n public isConfigStale(storageTimestamp: number): boolean {\r\n if (!storageTimestamp) {\r\n return true;\r\n }\r\n\r\n // 259200000 = 3 days in milliseconds\r\n if ((this.stalenessCheckTimestamp - storageTimestamp) > 259200000) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Function to check config on server cache is stale\r\n * @returns true if stale else false.\r\n */\r\n public isServerCacheConfigStale(storageTimestamp: number): boolean {\r\n if (!storageTimestamp) {\r\n return true;\r\n }\r\n\r\n // 300000 = 5 minutes in milliseconds\r\n if ((this.stalenessCheckTimestamp - storageTimestamp) > SERVER_CACHE_CONFIG_STALENESS_TIMEOUT) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Removes relative path from url and returns Config Index Href.\r\n * Input Example: cms/api/amp/experienceConfigIndex/ABCD\r\n * @returns string. Example: ABCD\r\n */\r\n public removeCmsPathFromRelativeUrl(relativeUrl: string): string {\r\n return relativeUrl.replace(\"cms/api/amp/experienceConfigIndex/\", \"\");\r\n }\r\n\r\n /**\r\n * Removes cached config from IndexedDB.\r\n */\r\n public removeCachedConfig(relativeUrl: string): void {\r\n // check if web worker and indexedDb use is allowed.\r\n if (this.useWebWorkerToCache && this.useIndexedDb) {\r\n // Send post message to web worker.\r\n sendToWebWorker({ id: \"clearconfigcache\", payload: relativeUrl });\r\n } else {\r\n // If web worker is not allowed, remove all configs from indexedDb as they are all stored as a single row.\r\n this.clearConfigCache();\r\n }\r\n }\r\n\r\n /**\r\n * This helper function is used to clear cached configs\r\n * @returns Promise\r\n */\r\n public async clearConfigCache(): Promise {\r\n if (this.useIndexedDb) {\r\n try {\r\n await this.initializeIndexedDb();\r\n\r\n try {\r\n await this.indexedDb.clearObjects();\r\n logger.log(`${this.logPrefix()} Cleared all configs from indexedDb.`);\r\n } catch {\r\n logger.logError(`${this.logPrefix()} Failed to clear all configs from indexedDb`);\r\n }\r\n } catch {\r\n logger.logError(`${this.logPrefix()} Failed to initialize indexedDb`);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * For testing purpose to access what has been set for configServiceParameters\r\n */\r\n public getConfigServiceParameters(): string {\r\n return this.configServiceParameters;\r\n }\r\n\r\n /**\r\n * Adds an entry into the config timings for the given type and relative start time\r\n */\r\n public addConfigTiming(experienceType: string, startTime: number, type: \"network\" | \"cache\"): void {\r\n this.configTimings.push({\r\n experienceType,\r\n [type + \"FetchDuration\"]: performance.now() - startTime\r\n });\r\n }\r\n\r\n /**\r\n * Helper function to get Config Timings\r\n * @param pageTimings _pageTimings object\r\n */\r\n public getConfigTimings(pageTimings: any = {}, getAllConfigTimingsOverride = false): void {\r\n if (!this.configTimings) {\r\n return;\r\n }\r\n\r\n let allConfigsCacheDuration = 0;\r\n let allConfigsNetworkDuration = 0;\r\n for (let configTiming of this.configTimings) {\r\n // Instrument networkFetchDuration and cacheFetchDuration\r\n const experienceType = configTiming.experienceType.toLowerCase();\r\n const cacheFetchDuration = configTiming.cacheFetchDuration;\r\n const networkFetchDuration = configTiming.networkFetchDuration;\r\n\r\n if (experienceType === \"entrypoint\"\r\n || experienceType === \"river\"\r\n || experienceType === \"contentpreview\"\r\n // when appropriate debug flag is set, output all config timings.\r\n || appEnvironment.IsDebug\r\n || getAllConfigTimingsOverride) {\r\n\r\n // Instrumenting networkFetchDuration to check effectiveness of get Config over the network for FRE.\r\n if (networkFetchDuration !== undefined) {\r\n pageTimings[\"ConfigFetch.\" + experienceType] = Math.round(networkFetchDuration);\r\n }\r\n\r\n // Instrumenting cacheFetchDuration to check effectiveness of storing merged config since it will be always used in non FRE.\r\n if (cacheFetchDuration !== undefined) {\r\n pageTimings[\"ConfigCache.\" + experienceType] = Math.round(cacheFetchDuration);\r\n }\r\n }\r\n\r\n if (cacheFetchDuration !== undefined) {\r\n allConfigsCacheDuration += cacheFetchDuration;\r\n }\r\n\r\n if (networkFetchDuration !== undefined) {\r\n allConfigsNetworkDuration += networkFetchDuration;\r\n }\r\n }\r\n\r\n if (allConfigsCacheDuration) {\r\n pageTimings[\"ConfigCache.All\"] = Math.round(allConfigsCacheDuration);\r\n }\r\n\r\n if (allConfigsNetworkDuration) {\r\n pageTimings[\"ConfigFetch.All\"] = Math.round(allConfigsNetworkDuration);\r\n }\r\n }\r\n\r\n /**\r\n * UNIT TEST PURPOSE: Function to set configTimings\r\n * @param ConfigFetchTiming[]\r\n */\r\n public setConfigTimingsObject(configFetchTimings: ConfigFetchTiming[]): void {\r\n this.configTimings = configFetchTimings;\r\n }\r\n\r\n /**\r\n * Get the cache key based on confix index url and the target scope generated suffix.\r\n * @param relativeUrl The config url\r\n * @returns The unique cache key for the merged config + target scope combination.\r\n */\r\n public getCacheKey(relativeUrl: string): string {\r\n return relativeUrl === null ? null : this.removeCmsPathFromRelativeUrl(relativeUrl) + \"_\" + this.storageKey;\r\n }\r\n\r\n /**\r\n * Get cached Configs from IndexedDb and populate configMap based on target scope key.\r\n */\r\n private async _populateConfigMapFromIndexedDbAsync(): Promise {\r\n\r\n let cacheSource: string;\r\n\r\n try {\r\n // Check if indexedDb is present, if not return.\r\n // Check if web worker is present, if not, indexedDb will not be refreshed since refreshConfigCache uses post message to web worker.\r\n // so you may get stale configs within 3 days of time range so this check is essential as well.\r\n // Check if we've previously attempted to read from IDB, and if don't do it again.\r\n if (!this.useIndexedDb || !this.useWebWorkerToCache) {\r\n return;\r\n }\r\n\r\n const startBulkConfig = performance.now();\r\n\r\n this.configMap.clear();\r\n let cachedConfigs: CachedConfigsType;\r\n\r\n // Optionally pre-initialized IDB config read promise at the top page level\r\n const { _idbConfigReadPromise, _idbConfigLookup } = window;\r\n\r\n // Check if we have a top page-level initialized IDB read config lookup populated\r\n // with the specific entry we need, and if so use it. Otherwise proceed to load from indexDB\r\n cachedConfigs = (_idbConfigLookup || {})[this.storageKey] as CachedConfigsType;\r\n if (cachedConfigs) {\r\n\r\n cacheSource = \"pre-initialized config cache\";\r\n\r\n } else if (_idbConfigReadPromise) {\r\n // see if we have the pre-initialized config read promise from IDB, and if so\r\n // await on that instead of starting our own duplicate IDB init/read.\r\n\r\n cacheSource = \"pre-initialized IndexedDb read\";\r\n await _idbConfigReadPromise;\r\n cachedConfigs = (window._idbConfigLookup || {})[this.storageKey] as CachedConfigsType;\r\n\r\n } else {\r\n\r\n // start our own IDB read.\r\n cacheSource = \"IndexedDb bulk read\";\r\n await this.initializeIndexedDb();\r\n cachedConfigs = await this.indexedDb.getObject(this.storageKey);\r\n }\r\n\r\n if (!cachedConfigs || cachedConfigs.size === 0) {\r\n logger.log(`${this.logPrefix()} Bulk read of configs from ${cacheSource} didn't find any configs.`);\r\n return;\r\n }\r\n\r\n this.populateConfigMapFromCachedConfigs(cachedConfigs, cacheSource);\r\n this.addConfigTiming(\"IdbInitAndReadAll\", startBulkConfig, \"cache\");\r\n\r\n } catch (e) {\r\n this.resolverErrors.push({\r\n ...ResolverAppErrors.IndexedDbBulkReadFailed,\r\n message: `IndexedDb bulk read from ${cacheSource} failed. Error: ${e}`\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize indexedDb for configs. Instead of using this directly, please use the memoized\r\n * initializeIndexedDb function instead to avoid re-entrancy of the same async operation.\r\n */\r\n private async _initializeIndexedDb(): Promise {\r\n if (!this.useIndexedDb) {\r\n return;\r\n }\r\n\r\n try {\r\n // IMPORTANT!! The wwConfigs name must be in sync with the PCS script that initializes the IDB and WebWorkerResolver\r\n const { _idbConfigOpenPromise } = window;\r\n await this.indexedDb.initializeIndexedDb(1, \"Configurations_12\", \"wwConfigs\", _idbConfigOpenPromise);\r\n logger.log(`${this.logPrefix()} IndexedDb initialized in main thread.`);\r\n } catch (e) {\r\n this.resolverErrors.push({\r\n ...ResolverAppErrors.IndexedDbInitFailed,\r\n message: `IndexedDb initialization failed. Error: ${e}`\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Populates the in-memory map object with the configs from cache\r\n */\r\n private populateConfigMapFromCachedConfigs(cachedConfigs: CachedConfigsType, cacheSource: string): void {\r\n\r\n // targetScopeKey is inserted into IndexedDb along with configIndexHref.\r\n // Although there can be more than type of keys being formed since DHP and NTP will have different ones due to pageType in targetScope.\r\n let unusableCount = 0;\r\n\r\n cachedConfigs.forEach(cachedConfig => {\r\n if (!cachedConfig.configIndexHref\r\n || this.isConfigStale(cachedConfig.storageTimestamp)) {\r\n\r\n unusableCount++;\r\n } else {\r\n let cacheKey = this.getCacheKey(cachedConfig.configIndexHref);\r\n\r\n this.configMap.set(cacheKey, cachedConfig);\r\n }\r\n });\r\n\r\n logger.log(`${this.logPrefix()} Found ${cachedConfigs.size - unusableCount} valid configs out of ${cachedConfigs.size} from ${cacheSource}`);\r\n }\r\n\r\n /**\r\n * Prefix for config resolver logs. Server side add the request id.\r\n * @returns the prefix string for logger message.\r\n */\r\n private logPrefix(): string {\r\n // Request Id is only available on server side.\r\n return `Config Resolver:${(canUseDOM() ? `` : ` [Request:${getRequestData().requestId}]`)}`;\r\n }\r\n}\r\n\r\n/**\r\n * Config Timings type to determine how much time each experience took to getConfig\r\n */\r\ninterface ConfigFetchTiming {\r\n /**\r\n * Experience Type\r\n */\r\n experienceType: string,\r\n\r\n /**\r\n * Time took to get configs over the network and merge them.\r\n */\r\n networkFetchDuration?: number,\r\n\r\n /**\r\n * Time took to get merged configs from cache.\r\n */\r\n cacheFetchDuration?: number\r\n}\r\n\r\n/** Resolver Singleton */\r\nlet _instance: Resolver = new Resolver();\r\n\r\n/** Reinitialize the singleton class instance. */\r\nexport function resetInstance(): void {\r\n _instance = new Resolver();\r\n}\r\n\r\nexport const resolver = {\r\n getConfig: (relativeUrl: string) => { return _instance.getConfig(relativeUrl); },\r\n mergeConfig: (configs: IExperienceConfig[]) => { return _instance.mergeConfig(configs); },\r\n resolveConfigIndex: (configIndex: IExperienceConfigIndex) => { return _instance.resolveConfigIndex(configIndex); },\r\n targetScopeMatched: (experienceRef: IExperienceConfigLink) => { return _instance.targetScopeMatched(experienceRef); },\r\n getConfigTimings: (pageTimings: any = {}, getAllConfigTimingsOverride = false) => { return _instance.getConfigTimings(pageTimings, getAllConfigTimingsOverride); },\r\n getResolverErrors: () => { return _instance.getResolverErrors(); },\r\n refreshConfigCache: () => { return _instance.refreshConfigCache(); },\r\n removeCachedConfig: (relativeUrl: string) => { return _instance.removeCachedConfig(relativeUrl); },\r\n clearConfigCache: () => { return _instance.clearConfigCache(); },\r\n getInstance: () => { return _instance; },\r\n\r\n // these are test specific exports\r\n overrideConfig: (relativeUrl: string, experienceType: string, config: any) => { return _instance.overrideConfig(relativeUrl, experienceType, config); },\r\n overrideCurrentRequestTargetScope: (targetScope: PageRequestTargetScope) => { return _instance.overrideCurrentRequestTargetScope(targetScope); },\r\n overrideCurrentRequestEnvironment: (overrideEnv: Environment) => { return _instance.overrideCurrentRequestEnvironment(overrideEnv); },\r\n generateKey: () => { return _instance.generateKey(); },\r\n clearInternalState: () => { return _instance.clearInternalState(); },\r\n initializeCaching: (idb?: IndexedDb) => { return _instance.initializeCaching(idb); },\r\n getConfigServiceParameters: () => { return _instance.getConfigServiceParameters(); },\r\n setConfigTimingsObject: (configFetchTimings: ConfigFetchTiming[]) => { return _instance.setConfigTimingsObject(configFetchTimings); }\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { PerfTimeline, logger, tryGetPerfTimeline } from \"@msnews/diagnostics\";\r\nimport { getIndexedDB, getLocationSearch } from \"@msnews/isomorphic-util\";\r\n\r\nimport { UrlUtility } from \"./UrlUtility\";\r\n\r\n/**\r\n * Provides utility functions to get and set data from IndexedDB.\r\n * If dbName is not provied, this class creates a db with name MicrosoftNews.\r\n * If storeName is not provied, this class creates a table/store with name Default.\r\n * Recommended to create a new table for your feature to separate and iterate through entries quickly.\r\n * IndexedDB utility does not require stringify and json parsing so more efficient! Just store your object as value.\r\n */\r\nexport class IndexedDb {\r\n\r\n /** IndexedDb object */\r\n private idb: IDBFactory = getIndexedDB();\r\n\r\n /** IndexedDb store name */\r\n /** DO NOT PUT DOT IN THE STORE NAME. */\r\n private storeName: string;\r\n\r\n /** IndexedDb promise. Sets when IndexedDB is initialized. */\r\n private idbPromise: Promise;\r\n\r\n /** The perf timeline for this IDB instance */\r\n private perfTimeline: PerfTimeline;\r\n\r\n /**\r\n * Returns if IndexedDb is supported.\r\n * @returns true if supported else false.\r\n */\r\n public get supported(): boolean {\r\n if (!this.idb) {\r\n logger.log(\"window.indexedDB is not supported.\");\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Function looks at query string param and check if IndexedDb operation is allowed or not. By default it is allowed.\r\n * @returns true if supported else false.\r\n */\r\n public get isCachingAllowed(): boolean {\r\n const searchObj = getLocationSearch();\r\n if (searchObj) {\r\n const param = UrlUtility.getQueryParameterByName(\"enableIndexedDbOperation\", searchObj);\r\n if (param) {\r\n return param.toLocaleLowerCase() === \"true\";\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Function looks at query string param and check if IndexedDb operation is allowed or not. By default it is allowed.\r\n * @returns true if supported else false.\r\n */\r\n public get isGetAllAllowed(): boolean {\r\n const searchObj = getLocationSearch();\r\n if (searchObj) {\r\n const param = UrlUtility.getQueryParameterByName(\"allowGetAllOverCursor\", searchObj);\r\n if (param) {\r\n return param.toLocaleLowerCase() === \"true\";\r\n }\r\n }\r\n\r\n if (IDBObjectStore.prototype && IDBObjectStore.prototype.getAll) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * This should be used for unit testing only.\r\n * @public\r\n * @param {IDBFactory} idb - IndexedDB object to override.\r\n */\r\n public _setIndexedDb(idb: IDBFactory): void {\r\n this.idb = idb;\r\n }\r\n\r\n /**\r\n * This should be used for unit testing only.\r\n * @public\r\n * @return {Promise} existing promise.\r\n */\r\n public _getIdbPromise(): Promise {\r\n return this.idbPromise;\r\n }\r\n\r\n /**\r\n * Returns object from IndexedDB\r\n * @public\r\n * @param {IDBValidKey} key - IndexedDB key. Typically it can be string or any supported type.\r\n * @returns Promise\r\n */\r\n public async getObject(key: IDBValidKey): Promise {\r\n let req: IDBRequest;\r\n\r\n await this.withIdbStore(\"readonly\", \"getObject\", storeCallback => {\r\n req = storeCallback.get(key);\r\n });\r\n return req.result;\r\n }\r\n\r\n /**\r\n * Return all objects from IndexedDB using getAll implementation.\r\n * @public\r\n * @returns Promise\r\n */\r\n public async getAll(): Promise {\r\n let req: IDBRequest;\r\n await this.withIdbStore(\"readonly\", \"getAll\", storeCallback => {\r\n req = storeCallback.getAll();\r\n });\r\n return req.result;\r\n }\r\n\r\n /**\r\n * Returns all objects from IndexedDB.\r\n * if getAll is supported, call it else fallback to Cursor implementation that exists on wide range of devices.\r\n * @public\r\n * @returns Promise\r\n */\r\n public async getAllObjects(): Promise {\r\n if (this.isGetAllAllowed) {\r\n return this.getAll();\r\n }\r\n\r\n let returnArray: Type[] = [];\r\n await this.withIdbStore(\"readonly\", \"getAllObjects\", storeCallback => {\r\n storeCallback.openCursor().onsuccess = function (event: any): void {\r\n const cursor = event.target && event.target.result ? event.target.result : undefined;\r\n if (cursor && cursor.value) {\r\n returnArray.push(cursor.value);\r\n cursor.continue();\r\n }\r\n };\r\n });\r\n return returnArray;\r\n }\r\n\r\n /**\r\n * Sets object into IndexedDB\r\n * @public\r\n * @param {IDBValidKey} key - IndexedDB key. Typically it can be string or any supported type.\r\n * @param {any} value - Any typed value you want to insert into IndexedDB.\r\n */\r\n public async setObject(key: IDBValidKey, value: any): Promise {\r\n return await this.withIdbStore(\"readwrite\", \"setObject\", storeCallback => {\r\n storeCallback.put(value, key);\r\n });\r\n }\r\n\r\n /**\r\n * Removes object from IndexedDB\r\n * @public\r\n * @param {IDBValidKey} key - IndexedDB key. Typically it can be string or any supported type.\r\n */\r\n public async removeObject(key: IDBValidKey): Promise {\r\n return await this.withIdbStore(\"readwrite\", \"removeObject\", storeCallback => {\r\n storeCallback.delete(key);\r\n });\r\n }\r\n\r\n /**\r\n * Removes all objects from IndexedDB\r\n * @public\r\n */\r\n public async clearObjects(): Promise {\r\n return await this.withIdbStore(\"readwrite\", \"clearObjects\", storeCallback => {\r\n storeCallback.clear();\r\n });\r\n }\r\n\r\n /**\r\n * Initialize IndexedDb.\r\n * @param idbStoreName {string} - IndexedDB store name\r\n * @param dbName {string} - Database name\r\n * @param preInitializedIdbPromise {Promise} - Optional pre-initialized promise that is fetching the {IDBDatabase} object.\r\n * Used to optimize/prime the IDB connection cost so it can be started as early as possible in the page without incurring additional cost\r\n * later when lot more things are happening on the page.\r\n */\r\n public async initializeIndexedDb(\r\n idbVersion: number = 1,\r\n idbStoreName: string = \"Default\",\r\n dbName: string = \"MicrosoftNews\",\r\n preInitializedIdbPromise: Promise = null\r\n ): Promise {\r\n\r\n this.storeName = idbStoreName;\r\n this.perfTimeline = tryGetPerfTimeline(`IndexedDB-${idbStoreName}`, idbStoreName);\r\n\r\n this.idbPromise = preInitializedIdbPromise || new Promise((resolve, reject) => {\r\n\r\n const endOpen = this.perfTimeline && this.perfTimeline.startMeasure(\"open\").endMeasure;\r\n const openreq = this.idb.open(dbName, idbVersion);\r\n\r\n openreq.onerror = () => {\r\n if (endOpen) { endOpen(\"error\"); }\r\n reject(openreq.error);\r\n };\r\n\r\n openreq.onsuccess = () => {\r\n if (endOpen) { endOpen(); }\r\n resolve(openreq.result);\r\n };\r\n\r\n openreq.onupgradeneeded = () => {\r\n openreq.result.createObjectStore(idbStoreName);\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Private function to set transaction.\r\n * @param type - IDB read/write mode\r\n * @param operationName - readable name to use in the app trace logging\r\n * @param callback - the callback to invoke with the IDB objectStore.\r\n * @returns {Promise} async operation that ends when the IDB transaction is complete.\r\n */\r\n private async withIdbStore(\r\n type: IDBTransactionMode,\r\n operationName: string,\r\n callback: ((store: IDBObjectStore) => void)\r\n ): Promise {\r\n\r\n return this.idbPromise.then(db => new Promise((resolve, reject) => {\r\n const endOperation = this.perfTimeline && this.perfTimeline.startMeasure(operationName).endMeasure;\r\n const transaction = db.transaction(this.storeName, type);\r\n\r\n transaction.oncomplete = () => {\r\n if (endOperation) { endOperation(); }\r\n resolve();\r\n };\r\n\r\n transaction.onabort = transaction.onerror = () =>\r\n reject(transaction.error);\r\n\r\n callback(transaction.objectStore(this.storeName));\r\n }));\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\nimport { MockLRUCache } from \"./ServerCacheMock\";\r\nimport LRUCache from \"lru-cache-for-clusters-as-promised\";\r\n\r\n/**\r\n * Clustered cache.\r\n * @type {LRUCache | MockLRUCache}\r\n */\r\nlet serverCache: LRUCache | MockLRUCache;\r\n\r\n/**\r\n * Initializes the serverCache with the LRUCache instance provided by the Render Service.\r\n * For testing it is initialized with a mock instance.\r\n * This needs to be called once on the server side.\r\n * @param cache\r\n */\r\nfunction initialize(cache: LRUCache | MockLRUCache): void {\r\n serverCache = cache;\r\n}\r\n\r\n/**\r\n * Reset the serverCache, clearing all data from the cache.\r\n * Currently only used for unit tests.\r\n * @returns {ServerCache}\r\n */\r\nfunction reset(): void {\r\n serverCache.reset();\r\n}\r\n\r\n/**\r\n * Set cache. Update the \"recently used\"-ness of the key.\r\n * @param key Cache key to set.\r\n * @param value Cache value to set.\r\n * @param maxAge Optional maximum age in milliseconds.\r\n */\r\nasync function set(key: string, value: any, maxAge?: number): Promise {\r\n if (maxAge) {\r\n await serverCache.set(key, value, maxAge);\r\n } else {\r\n await serverCache.set(key, value);\r\n }\r\n}\r\n\r\n/**\r\n * Get cache. Update the \"recently used\"-ness of the key.\r\n * @param key Cache key to get.\r\n * @returns Cached object. If not found, return undefined.\r\n */\r\nasync function get(key: string): Promise {\r\n return await serverCache.get(key);\r\n}\r\n\r\n/**\r\n * Check if a key is in the cache, without updating the recent-ness or deleting it for being stale.\r\n * @param key Cache key to check.\r\n * @returns True if key exists.\r\n */\r\nasync function has(key: string): Promise {\r\n return await serverCache.has(key);\r\n}\r\n\r\n/**\r\n * Removes a value from the cache.\r\n * @param key Cache key to delete.\r\n * @returns Promise for completing the task\r\n */\r\nasync function del(key: string): Promise {\r\n return await serverCache.del(key);\r\n}\r\n\r\n/**\r\n * Return total quantity of objects currently in cache. Note, that stale (see options) items are returned as part of this item count.\r\n * @returns Total quantity of objects currently in cache.\r\n */\r\nasync function itemCount(): Promise {\r\n return await serverCache.itemCount();\r\n}\r\n\r\n/**\r\n * ServerCache is server side only data cache.\r\n * More detailed docs are in the following links\r\n * https://github.com/isaacs/node-lru-cache#readme\r\n * https://github.com/doublesharp/lru-cache-for-clusters-as-promised\r\n */\r\nexport const ServerCache = (!canUseDOM()) ? {\r\n initialize,\r\n reset,\r\n set,\r\n get,\r\n has,\r\n del,\r\n itemCount\r\n} : null;\r\n\r\n// Initialize ServerCache using mock cache for tests, we do it here so it works for relative imports\r\nif (global[\"TEST_ENV\"] && !canUseDOM()) {\r\n ServerCache.initialize(new MockLRUCache());\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { DynamicReducer, IReducer } from \"../reducers\";\r\nimport { PerfTimeline, tryGetPerfTimeline } from '@msnews/diagnostics';\r\nimport { Subspace, subspace } from \"redux-subspace\";\r\nimport { merge as _merge, set as _set } from \"lodash-es\";\r\n\r\nimport { ConnectorConstants } from \"../constants/ConnectorConstants\";\r\nimport { IDataConnector } from \"./IDataConnector\";\r\nimport { Store } from \"redux\";\r\n\r\n/**\r\n * Base class for data connectors.\r\n * A Data connector is a the base for all connectors in a msnews-experiences-redux application. The data connector has\r\n * the methods and properties that manage a state object, which can either be a sub-state within the app, or the full\r\n * application state tree\r\n * @class\r\n */\r\nexport class DataConnector implements IDataConnector {\r\n /**\r\n * The Redux subspace store for this connector\r\n * @type {Subspace}\r\n */\r\n protected _subspace: Subspace;\r\n\r\n /**\r\n * The full namespace, including all of the ancestors, in dotted notation:\r\n * i.e.: parent.child.grandchild\r\n */\r\n private _fullNamespace: string;\r\n\r\n /**\r\n * The perf timeline object for this connector\r\n */\r\n private _perfTimeline: PerfTimeline;\r\n\r\n /**\r\n * The config href for the connector\r\n */\r\n private _configHref: string;\r\n\r\n /**\r\n * Gets the Redux store for this data connector instance, which is a subspace within the parent state\r\n * @property\r\n * @returns {Store} The state subspace for this connector, which looks like a Redux Store\r\n */\r\n public get store(): Store {\r\n return this._subspace;\r\n }\r\n\r\n /**\r\n * Gets the full namespace for this connector\r\n * @property\r\n * @returns {string} The connector's full namespace\r\n */\r\n public get fullNamespace(): string {\r\n return this._fullNamespace;\r\n }\r\n\r\n /**\r\n * The perf timeline object for this connector\r\n */\r\n public get perfTimeline(): PerfTimeline {\r\n return this._perfTimeline;\r\n }\r\n\r\n /**\r\n * Get the config href for the connector\r\n */\r\n public get configHref(): string {\r\n return this._configHref;\r\n }\r\n /**\r\n * Set the config href for the connector\r\n */\r\n public set configHref(href: string) {\r\n this._configHref = href;\r\n }\r\n\r\n /**\r\n * Construct a new Data connector\r\n * @constructor\r\n * @param { string } namespace The redux subspace namespace for the connector\r\n * @param { string } parentNamespace The redux subspace namespace for the parent connector, if it exists\r\n * @param { DynamicReducer } rootReducer The root reducer for the Application\r\n * @param { IReducer } reducer The reducer for this connector instance\r\n * @param { Store} parentStore The parent store (or redux subspace) that this connector will be a subspace within\r\n * @param { TConfig } config Optional param containing the config for the connector\r\n * @param { boolean } isGlobal Optional param to set if the connector should be global or not. Defaults to false\r\n */\r\n public constructor(\r\n public readonly namespace: string,\r\n public readonly parentNamespace: string,\r\n public readonly rootReducer: DynamicReducer,\r\n public readonly reducer: IReducer,\r\n parentStore: Store,\r\n public readonly config?: TConfig,\r\n public readonly isGlobal: boolean = false) {\r\n // Setup the full namespace. This namespace will be used as the parentNamespace to any connectors created as children of this\r\n // connector. It is the \"dotted\" concatenation of the parentNamespace + namespace, which represents the key into the state tree for the child connectors\r\n this._fullNamespace = (typeof parentNamespace !== \"undefined\" && parentNamespace !== \"\") ? parentNamespace + \".\" + namespace : namespace;\r\n\r\n // setup the sub-spaced store with a state selector that is bound to this connector's instance, and returns the inner state object (TState) for this connector\r\n this.selectState = this.selectState.bind(this);\r\n this._subspace = subspace(this.selectState, this.namespace)(parentStore);\r\n\r\n // try to create a perf timeline for this connector\r\n this._perfTimeline = this.tryGetPerfTimeline(namespace);\r\n\r\n rootReducer.addSubReducerForConnector(this);\r\n }\r\n\r\n /**\r\n * Gets the current state of the connector. The connector's state (TState) is the sub-portion of the returned state object with the postfix \"State\"\r\n * This is because the overall subspace state for the connector will contain the children states as well\r\n * @method\r\n * @returns {TState} The current state of the component.\r\n */\r\n public getCurrentState(): TState {\r\n // Get the subspace state for this connector. It will be something like:\r\n // { _@STATE@_ : { TState }}, where the subspace selector will already have been used to get the namespaced substate\r\n const wrappedState: TState = this.store.getState();\r\n\r\n // Get the currentState, that will be returned. By default it wil be just the state for this controller\r\n let connectorState = wrappedState[ConnectorConstants.connectorStateKey];\r\n\r\n // If the connector's state is not global, then check to see if there are any global connectors it needs to be merged with\r\n // If the connector is global, then its state is just returned, otherwise we would have an infinte loop merging a global connectors's\r\n // state with itself.\r\n if (!this.isGlobal) {\r\n // Get the list of global connectors\r\n let globalConnectors = this.rootReducer.globalConnectors();\r\n\r\n // See if there are any global connectors that need to be merged in.\r\n if (globalConnectors.length !== 0) {\r\n // For each global connector, merge it's state into the final result, using the global connector's namespace\r\n // So the resulting state will be:\r\n // { globalConnectorNamespace: { state }, TSTATE }}\r\n globalConnectors.forEach(globalConnector => {\r\n _set(connectorState, globalConnector.namespace, globalConnector.getCurrentState());\r\n });\r\n }\r\n }\r\n return connectorState;\r\n }\r\n\r\n /**\r\n * The method is called as the application is starting up, components are created.\r\n * The method can be used by connectors to perform one time initialization functions\r\n * This method needs to be overridden if your connector has specific startup needs\r\n * @method\r\n * @returns void\r\n */\r\n public onApplicationStart(): void { /** no-op */ }\r\n\r\n /**\r\n * The subspace selector that gets the portion of the state tree that is for this connector\r\n * @param state The parent state object that contains the subspace\r\n */\r\n private selectState(state: TParentState): TState {\r\n return (state[this.namespace]);\r\n }\r\n\r\n /**\r\n * Attempts to create the {PerfTimeline} object for this connector\r\n */\r\n private tryGetPerfTimeline(namespace: string): PerfTimeline {\r\n\r\n const namespaceParts = namespace.split(\"_\");\r\n const [connectorType] = namespaceParts;\r\n\r\n // there may not be any instance id -- in which case this would simply be the connector type.\r\n const instanceId = namespaceParts[namespaceParts.length - 1];\r\n\r\n // get the perf timeline object if applicable to the current experience\r\n return tryGetPerfTimeline(connectorType, instanceId);\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * The \"DeferralHandlerSignature\" is a callback signature is called used when an experience is deferred on the callback to be resolved.\r\n * This callback should return a Promise that resolves with a boolean.\r\n */\r\nexport type DeferralHandlerSignature = () => Promise;\r\n\r\n/**\r\n * Deferral type of an experience\r\n */\r\nexport enum DeferralEventType {\r\n /**\r\n * Standard Deferral Event Type based on page/experience lifecycle based events like AboveTheFoldReady or other experience available\r\n */\r\n StandardEventBasedDeferral = 0,\r\n\r\n /**\r\n * Custom Deferral Event Type based like belowTheFoldTransitionStart which hoooked to work with UI events like intersectionObserver.\r\n */\r\n CustomEventBasedDeferral = 1\r\n}\r\n\r\n/**\r\n * Type to resolve deferral info to calling code\r\n */\r\nexport interface ExperienceDeferralMetadata {\r\n /**\r\n * Deferral type of an experience\r\n */\r\n deferralType: DeferralEventType;\r\n\r\n /**\r\n * A callback that resolves with a bool to specify when the experience is ready to load/render\r\n */\r\n shouldResolve: DeferralHandlerSignature\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Defines valid milestone event types\r\n */\r\nexport enum ExperienceMilestoneEventTypes {\r\n /**\r\n * Fired when all the initial DOM elements for the experience have been added (i.e. onComponentDidMount)\r\n * The DOM may not be completely rendered by the browser when then milestone is reached\r\n */\r\n domComplete,\r\n\r\n /**\r\n * Fired if the experience hits an unrecoverable error\r\n */\r\n error,\r\n\r\n /**\r\n * Fired when the experience is initialized\r\n */\r\n initialized,\r\n\r\n /**\r\n * Fired when the experience is initially rendered. This is after the browser has processed all of the DOM elements that were\r\n * added in the experience render function.\r\n */\r\n rendered,\r\n\r\n /**\r\n * Fired when the experience is visually ready, which is a business metric and defined in the MSNews Performance Metrics documentation.\r\n */\r\n visuallyReady\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nexport enum ExperienceCompositionTypes {\r\n grid = \"grid\",\r\n horizontalStack = \"horizontalStack\",\r\n layout = \"layout\",\r\n verticalStack = \"verticalStack\",\r\n customExperience = \"customExperience\"\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * An enumeration of possible children types that can be rendered into a layout column\r\n */\r\nexport enum ChildrenTypes {\r\n /**\r\n * A Fast DNA ActionTrigger component\r\n */\r\n actionTrigger = \"ActionTrigger\",\r\n /**\r\n * A Fast DNA Button component\r\n */\r\n button = \"Button\",\r\n\r\n /**\r\n * A Fast DNA Heading component\r\n */\r\n heading = \"Heading\",\r\n\r\n /**\r\n * A Peregrine Experience\r\n */\r\n peregrineExperience = \"PeregrineExperience\",\r\n\r\n /**\r\n * A Fast DNA Typography component\r\n */\r\n typography = \"Typography\"\r\n}","\r\n// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Enum to describe screen width(column types)\r\n */\r\nexport enum ScreenWidth {\r\n OneColumn = \"OneColumn\",\r\n TwoColumn = \"TwoColumn\",\r\n ThreeColumn = \"ThreeColumn\",\r\n FourColumn = \"FourColumn\",\r\n Any = \"Any\"\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ExperienceLoadingState } from \"./ExperienceLoadingState\";\r\n\r\n/**\r\n * Defines custom deferral event types which is not part of page/experience lifecycle event types\r\n */\r\nexport enum CustomDeferralEventTypes {\r\n\r\n /**\r\n * The page level milestone when experiences outside the viewport are transitioning into viewport\r\n */\r\n belowTheFoldTransitionStart\r\n }\r\n\r\n/**\r\n * Defines valid deferral events used during milestone tracking\r\n * The event types should be mapped with loading types so that they have the exact same numeric value.\r\n */\r\nexport enum ExperienceDeferralEventTypes {\r\n\r\n /**\r\n * The loaded milestone of dependent experience\r\n */\r\n loaded = ExperienceLoadingState.loaded,\r\n\r\n /**\r\n * The rendered milestone of dependent experience\r\n */\r\n rendered = ExperienceLoadingState.rendered,\r\n\r\n /**\r\n * The domComplete milestone of dependent experience\r\n */\r\n domComplete = ExperienceLoadingState.domComplete,\r\n\r\n /**\r\n * The visuallyReady milestone of dependent experience\r\n */\r\n visuallyReady = ExperienceLoadingState.visuallyReady,\r\n\r\n /**\r\n * The page level milestone when experiences in viewport are visuallyReady\r\n */\r\n aboveTheFoldVisuallyReady,\r\n\r\n /**\r\n * The page level milestone when experiences outside the viewport are transitioning into viewport\r\n */\r\n belowTheFoldTransitionStart = CustomDeferralEventTypes.belowTheFoldTransitionStart\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Default key value for looking up experience instances\r\n */\r\nexport const defaultInstanceKeyName: string = \"default\";\r\n\r\n/**\r\n * Default time value for start/end time\r\n */\r\nexport const defaultTimeValue: number = -1;\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ExperienceDeferralEventTypes, ExperienceDeferralInfo } from \"../data-model\";\r\n\r\nimport { ExperienceLoadingState } from \"../data-model/ExperienceLoadingState\";\r\nimport { IActionPayload } from \"@msnews/experiences-redux\";\r\nimport { MilestoneDataActions } from \"../MilestoneData.actions\";\r\nimport { getMilestoneDataConnector } from \"../MilestoneData.Helper\";\r\n\r\n/**\r\n * Identifies a referenced experience and its dependents\r\n */\r\nexport interface ExperienceDependents {\r\n /**\r\n * Determines the state of deferral identifier experience.\r\n */\r\n currentState: ExperienceLoadingState;\r\n\r\n /**\r\n * The dependent set of experiences and its associated state mapped to a deferred event type.\r\n * An experience moves from deferred to resolvedForLoad or resolvedForRender state when deferral identifier experienceType/Group currentState matches deferred state.\r\n */\r\n referencedDependentsDeferralMap: Map>\r\n}\r\n\r\n// Keeps track of Experience Identifier to its referenced dependents mapping for loadAfter/renderAfter scenario\r\n// Experience Identifier, acts as a reference to resolve its dependents.\r\n// The key (experienceIdentifier) should be either experienceType or experienceGroup\r\nlet experienceDeferralDependencyMap: Map = new Map();\r\n\r\n/**\r\n * Resolves experience dependency\r\n * @param experienceType - experience loaded/rendered\r\n * @param experienceDependencyMap - experience dependency map to be updated\r\n */\r\nfunction resolveExperienceDependency(): void {\r\n\r\n MilestoneDataActions.updateExperienceCurrentState.registerObserver((actionPayload: IActionPayload) => {\r\n // Make sure this is a rendered state change\r\n if (!actionPayload.params ||\r\n !actionPayload.params[0] ||\r\n !actionPayload.params[1]) {\r\n return;\r\n }\r\n\r\n const experienceType = actionPayload.params[0];\r\n const experienceCurrentState = actionPayload.params[1];\r\n\r\n const expDependencies = experienceDeferralDependencyMap.get(experienceType);\r\n\r\n if (!expDependencies) {\r\n return;\r\n }\r\n\r\n expDependencies.currentState = experienceCurrentState;\r\n const deferralEventDependents = expDependencies.referencedDependentsDeferralMap.get(experienceCurrentState);\r\n\r\n if (!deferralEventDependents) {\r\n return;\r\n }\r\n\r\n deferralEventDependents.forEach((deferredState, dependentExp) => {\r\n if (!dependentExp) {\r\n return;\r\n }\r\n\r\n const resolvedState = deferredState === ExperienceLoadingState.loadDeferred ?\r\n ExperienceLoadingState.resolvedForLoad\r\n : ExperienceLoadingState.resolvedForRender;\r\n\r\n const milestoneDataConnector = getMilestoneDataConnector();\r\n if (milestoneDataConnector) {\r\n MilestoneDataActions.updateExperienceCurrentState.getActionSender(milestoneDataConnector)\r\n .send(dependentExp, resolvedState);\r\n }\r\n });\r\n\r\n });\r\n}\r\n\r\n/**\r\n * Update experience dependency map with new experience deferred information\r\n * @param actionPayload - actionPayload contains experience deferral information\r\n * @param experienceDependencyMap - experience dependency map to be updated\r\n */\r\nfunction updateExperienceDependencyMap(experienceType: string, expDeferralInfo: ExperienceDeferralInfo, deferredState: ExperienceLoadingState): void {\r\n\r\n if (!experienceType\r\n || !expDeferralInfo\r\n || !(expDeferralInfo.eventType in ExperienceDeferralEventTypes)\r\n || !(expDeferralInfo.experienceType || expDeferralInfo.experienceGroup)) {\r\n return;\r\n }\r\n\r\n const deferralEventType = expDeferralInfo.eventType;\r\n const expDeferralIdentifier = expDeferralInfo.experienceType || expDeferralInfo.experienceGroup;\r\n const existingDependentsInfo = experienceDeferralDependencyMap.get(expDeferralIdentifier);\r\n const dependents = new Map();\r\n\r\n if (!existingDependentsInfo || !existingDependentsInfo.referencedDependentsDeferralMap) {\r\n const referencedDependentsDeferralMap = new Map>();\r\n dependents.set(experienceType, deferredState);\r\n referencedDependentsDeferralMap.set(deferralEventType, dependents);\r\n experienceDeferralDependencyMap.set(expDeferralIdentifier,\r\n { currentState: ExperienceLoadingState.notStarted,\r\n referencedDependentsDeferralMap: referencedDependentsDeferralMap });\r\n return;\r\n } else {\r\n\r\n if (existingDependentsInfo.currentState >= expDeferralInfo.eventType) {\r\n // if deferral identifier eventType is already met, return and don't add dependencies\r\n return;\r\n }\r\n\r\n if (!existingDependentsInfo.referencedDependentsDeferralMap.has(deferralEventType)) {\r\n dependents.set(experienceType, deferredState);\r\n existingDependentsInfo.referencedDependentsDeferralMap.set(deferralEventType, dependents);\r\n } else {\r\n const existingDependents = existingDependentsInfo.referencedDependentsDeferralMap.get(expDeferralInfo.eventType);\r\n if (existingDependents.size > 0) {\r\n existingDependents.set(experienceType, deferredState);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * register observer to update experience load dependency map\r\n */\r\nfunction registerExperienceLoadDeferralObserver(): void {\r\n MilestoneDataActions.updateExperienceLoadDeferralState.registerObserver((actionPayload: IActionPayload) => {\r\n if (!actionPayload.params &&\r\n !actionPayload.params[0] &&\r\n actionPayload.params[0].eventType !== ExperienceDeferralEventTypes.loaded &&\r\n !actionPayload.params[1]) {\r\n return;\r\n }\r\n\r\n updateExperienceDependencyMap(actionPayload.params[1], actionPayload.params[0], ExperienceLoadingState.loadDeferred);\r\n });\r\n}\r\n\r\n/**\r\n * Register observer to update experience render dependency map\r\n */\r\nfunction registerExperienceRenderDeferralObserver(): void {\r\n MilestoneDataActions.updateExperienceRenderDeferralState.registerObserver((actionPayload: IActionPayload) => {\r\n if (!actionPayload.params &&\r\n !actionPayload.params[0] &&\r\n actionPayload.params[0].eventType !== ExperienceDeferralEventTypes.rendered &&\r\n !actionPayload.params[1]) {\r\n return;\r\n }\r\n\r\n updateExperienceDependencyMap(actionPayload.params[1], actionPayload.params[0], ExperienceLoadingState.renderDeferred);\r\n });\r\n}\r\n\r\n/**\r\n * registers observers to add and resolve experience dependencies\r\n */\r\nexport function startExperinceDeferralDependencyObserver(): void {\r\n registerExperienceLoadDeferralObserver();\r\n registerExperienceRenderDeferralObserver();\r\n resolveExperienceDependency();\r\n}\r\n\r\n/**\r\n * Checks if experience's dependency is resolved\r\n * @returns true if dependent experience has been resolved.\r\n * @param experienceDependency - dependent experience\r\n * @param deferralEventType - deferral EventType\r\n */\r\nexport function isExperienceDependencyResolved(experienceDependency: string, deferralEventType: ExperienceDeferralEventTypes): boolean {\r\n\r\n const deferralIdentifier = experienceDeferralDependencyMap.get(experienceDependency);\r\n\r\n if (!deferralIdentifier) {\r\n return true;\r\n }\r\n\r\n return deferralIdentifier.currentState >= deferralEventType;\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { CustomDeferralEventTypes, DeferralEventType, ExperienceDeferralEventTypes, ExperienceDeferralInfo, ExperienceDeferralMetadata } from \"./data-model\";\r\nimport { IActionPayload, PageBase } from \"@msnews/experiences-redux\";\r\nimport { defaultInstanceKeyName, defaultTimeValue } from \"./MilestoneData.constants\";\r\n\r\nimport { ConnectorNamespaces } from \"@msnews/experiences-constants\";\r\nimport { ExperienceInstanceMilestoneModel } from \"./data-model/ExperienceInstanceMilestoneModel\";\r\nimport { MilestoneDataActions } from \"./MilestoneData.actions\";\r\nimport { MilestoneDataConnector } from \"./MilestoneData.connector\";\r\nimport { MilestonePluginEvents } from \"./data-model/MilestonePluginEvents\";\r\nimport { isExperienceDependencyResolved } from \"./data-management\";\r\nimport { pluginUtils } from \"./utils/MilestonePluginUtils\";\r\n\r\n/**\r\n * Helper method to get the milestone data connector instance.\r\n * @returns Milestone data connector promise.\r\n */\r\nexport function getMilestoneDataConnector(): MilestoneDataConnector {\r\n return PageBase.getInstance().rootReducer.connector(\r\n ConnectorNamespaces.MilestoneData\r\n ) as MilestoneDataConnector;\r\n}\r\n\r\n/**\r\n * Helper method to get default instance of an experience.\r\n * @returns Experience Milestone instance data.\r\n */\r\nexport function getDefaultExperienceInstance(\r\n experienceType: string\r\n): ExperienceInstanceMilestoneModel {\r\n let connector = getMilestoneDataConnector();\r\n\r\n if (!connector) {\r\n return;\r\n }\r\n\r\n let milestones = connector.getCurrentState().perExperienceMilestones;\r\n let experience = milestones && milestones.get(experienceType);\r\n let instance: ExperienceInstanceMilestoneModel;\r\n\r\n if (experience) {\r\n instance = experience.perInstanceMilestones.get(defaultInstanceKeyName);\r\n }\r\n\r\n return instance;\r\n}\r\n\r\n/**\r\n * returns promise based experience load delegate, which resolves when experience dependent event is fired.\r\n * @returns A callback promise which resolves to boolean when associated experience is ready to be loaded\r\n * If null is returned experience is not deferred and should be loaded/rendered right away.\r\n */\r\nexport function getExperienceLoadDelegate(\r\n experienceType: string\r\n): ExperienceDeferralMetadata {\r\n\r\n let instance: ExperienceInstanceMilestoneModel = getDefaultExperienceInstance(experienceType);\r\n\r\n // return null if dependent deferral event has already been fired\r\n if (!instance || getDeferralLoadEventReadyState(instance)) {\r\n return null;\r\n }\r\n\r\n if (instance.shouldLoad && instance.loadAfter) {\r\n\r\n const deferralEventType = getDeferralEventMetadata(instance.loadAfter);\r\n return { deferralType: deferralEventType, shouldResolve: instance.shouldLoad };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * returns a promise that is resolved when\r\n * Milestone data connector was not initialized\r\n * Milestone data connector has already fired the above the fold visual ready action\r\n * Milestone data connector hasn't fired above the fold visual ready action so an observer is\r\n * set on the action to resolve the promise when that callback is invoked\r\n */\r\nexport function waitForAboveTheFoldVisuallyReadyAsync(): Promise {\r\n const milestoneDataConnector = getMilestoneDataConnector();\r\n\r\n if (!milestoneDataConnector) {\r\n return Promise.resolve();\r\n }\r\n\r\n if (isAboveTheFoldVisuallyReady()) {\r\n return Promise.resolve();\r\n }\r\n\r\n return new Promise(resolve => {\r\n MilestoneDataActions.updateAboveTheFoldVisuallyReady.registerObserver(((actionPayload: IActionPayload) => {\r\n resolve();\r\n }));\r\n });\r\n}\r\n\r\n/**\r\n * returns promise based experience render delegate, which resolves when experience dependent event is fired.\r\n * @returns A callback promise which resolves to boolean when associated experience is ready to be rendered.\r\n * If null is returned experience is not deferred and should be loaded/rendered right away.\r\n */\r\nexport function getExperienceRenderDelegate(\r\n experienceType: string\r\n): ExperienceDeferralMetadata {\r\n\r\n let instance: ExperienceInstanceMilestoneModel = getDefaultExperienceInstance(experienceType);\r\n\r\n // return null if dependent deferral event has already been fired\r\n if (!instance || getDeferralRenderEventReadyState(instance)) {\r\n return null;\r\n }\r\n\r\n if (instance.shouldRender && instance.renderAfter) {\r\n\r\n const deferralEventType = getDeferralEventMetadata(instance.renderAfter);\r\n return { deferralType: deferralEventType, shouldResolve: instance.shouldRender };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Execute milestone event hooks\r\n */\r\nexport async function executeMilestoneEventPlugins(eventType: MilestonePluginEvents): Promise {\r\n\r\n let connector = getMilestoneDataConnector();\r\n\r\n if (!connector) {\r\n return;\r\n }\r\n\r\n const plugins = connector.getCurrentState().plugins;\r\n\r\n if (!plugins || plugins.length === 0) {\r\n return;\r\n }\r\n\r\n const filteredPlugins = pluginUtils.filter(plugins, eventType);\r\n\r\n for (let plugin of filteredPlugins) {\r\n await plugin[eventType]!.call(plugin);\r\n }\r\n}\r\n\r\n/**\r\n * Return dependent deferral event ready state\r\n * @param instance - Experience instance\r\n */\r\nfunction getDeferralLoadEventReadyState(instance: ExperienceInstanceMilestoneModel): boolean {\r\n\r\n let deferralEventReady: boolean;\r\n\r\n switch (instance.loadAfter.eventType) {\r\n case ExperienceDeferralEventTypes.aboveTheFoldVisuallyReady:\r\n deferralEventReady = isAboveTheFoldVisuallyReady();\r\n break;\r\n\r\n case ExperienceDeferralEventTypes.belowTheFoldTransitionStart:\r\n deferralEventReady = isBelowTheFoldTransitionStarted();\r\n break;\r\n\r\n default:\r\n deferralEventReady = isExperienceDependencyResolved(instance.loadAfter.experienceType, instance.loadAfter.eventType);\r\n }\r\n\r\n return deferralEventReady;\r\n}\r\n\r\n/**\r\n * Return dependent deferral event ready state\r\n * @param instance - Experience instance\r\n */\r\nfunction getDeferralRenderEventReadyState(instance: ExperienceInstanceMilestoneModel): boolean {\r\n\r\n let deferralEventReady: boolean;\r\n\r\n switch (instance.renderAfter.eventType) {\r\n case ExperienceDeferralEventTypes.aboveTheFoldVisuallyReady:\r\n deferralEventReady = isAboveTheFoldVisuallyReady();\r\n break;\r\n\r\n case ExperienceDeferralEventTypes.belowTheFoldTransitionStart:\r\n deferralEventReady = isBelowTheFoldTransitionStarted();\r\n break;\r\n\r\n default:\r\n deferralEventReady = isExperienceDependencyResolved(instance.loadAfter.experienceType, instance.renderAfter.eventType);\r\n }\r\n\r\n return deferralEventReady;\r\n}\r\n\r\n/**\r\n * Returns true if above the fold is ready\r\n */\r\nfunction isAboveTheFoldVisuallyReady(): boolean {\r\n let connector = getMilestoneDataConnector();\r\n\r\n if (!connector) {\r\n return false;\r\n }\r\n\r\n return Boolean(connector.getCurrentState().aboveTheFoldVisuallyReady &&\r\n connector.getCurrentState().aboveTheFoldVisuallyReady.endTime !== defaultTimeValue);\r\n}\r\n\r\n/**\r\n * Returns true if above the fold is ready\r\n */\r\nfunction isBelowTheFoldTransitionStarted(): boolean {\r\n let connector = getMilestoneDataConnector();\r\n\r\n if (!connector) {\r\n return false;\r\n }\r\n\r\n return connector.getCurrentState().belowTheFoldTransitionStart;\r\n}\r\n\r\n/**\r\n * Update deferral event metadata\r\n * @param deferralInfo - Tracks deferral information used by an experience to determine when it should load/render\r\n * @returns - DeferralEventType, this can be either standard or custom depending upon what type of deferral has been used for experience deferral\r\n */\r\nfunction getDeferralEventMetadata(deferralInfo: ExperienceDeferralInfo): DeferralEventType {\r\n return deferralInfo.eventType in CustomDeferralEventTypes\r\n ? DeferralEventType.CustomEventBasedDeferral\r\n : DeferralEventType.StandardEventBasedDeferral;\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * class defining perf trackers.\r\n */\r\nexport class PerfTracker {\r\n\r\n /** The perf tracker end time. */\r\n private endTime: number = -1;\r\n\r\n /** The perf tracker start time. */\r\n private startTime: number = -1;\r\n\r\n /**\r\n * Get perf tracker time duration\r\n */\r\n public getDuration(): number {\r\n let result = -1;\r\n if (this.startTime !== -1 && this.endTime !== -1) {\r\n result = this.endTime - this.startTime;\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * get perf tracker end time\r\n */\r\n public getEnd(): number {\r\n return this.endTime;\r\n }\r\n\r\n /**\r\n * get perf tracker start time\r\n */\r\n public getStart(): number {\r\n return this.startTime;\r\n }\r\n\r\n /**\r\n * set perf tracker end time\r\n */\r\n public setEnd(): void {\r\n this.endTime = performance.now();\r\n }\r\n\r\n /**\r\n * set perf tracker start time\r\n */\r\n public setStart(): void {\r\n this.startTime = performance.now();\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ExperienceMilestoneEventTypes, MilestoneDataActions } from \"@msnews/milestone-data\";\r\nimport Foundation, { FoundationProps } from \"@microsoft/fast-components-foundation-react\";\r\nimport { PerfTracker, logger, markTtvr } from \"@msnews/diagnostics\";\r\n\r\nimport { MnsCreatorDashboardAttributes } from \"./MnsCreatorDashboard.attributes\";\r\nimport { appEnvironment } from \"@msnews/core\";\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\n\r\ndeclare global {\r\n interface Window {\r\n /**\r\n * Boolean flag to indicate if render cache hydration is happening\r\n */\r\n needsHydrate?: boolean;\r\n }\r\n}\r\n\r\n/** Type definition for the onExperienceMilestoneTimingUpdate callback */\r\nexport type ExperienceMilestoneTimingUpdate = (milestoneType: ExperienceMilestoneEventTypes,\r\n startTime?: number,\r\n endTime?: number) => void;\r\n\r\n/**\r\n * Common props for all experiences\r\n */\r\nexport interface CommonExperienceProps {\r\n /** The experience name. */\r\n experienceName?: string;\r\n\r\n /** Custom Field per experience when sending beacon to Cosmos. */\r\n customField?: string;\r\n\r\n /**\r\n * Handler function for Experience Milestone timing updates\r\n */\r\n onExperienceMilestoneTimingUpdate?: ExperienceMilestoneTimingUpdate\r\n}\r\n\r\n/**\r\n * TODO: This class may need to be sampled collecting and sending Perf timings if the traffic goes beyond a certain reach.\r\n * Assessment will be performed later after analyzing the data.\r\n */\r\nexport class BaseExperience extends Foundation {\r\n /** Perf marker for tracking Visually Reading timing */\r\n protected visuallyReadyTracker: PerfTracker = new PerfTracker();\r\n\r\n /** Perf marker for tracking Initialization timing */\r\n protected initializedTracker: PerfTracker = new PerfTracker();\r\n\r\n /** Perf marker for tracking DomComplete timing */\r\n protected domCompleteTracker: PerfTracker = new PerfTracker();\r\n\r\n /**\r\n * The constructor.\r\n * @param props - The props\r\n * @param context - The context\r\n */\r\n constructor(props: H & U & CommonExperienceProps & FoundationProps, context?: any) {\r\n super(props);\r\n\r\n this.startInitializeMilestone();\r\n this.startVisuallyReadyMilestone();\r\n this.startDomCompleteMilestone();\r\n }\r\n\r\n /**\r\n * Default react hook.\r\n */\r\n public componentDidMount(): void {\r\n // End the domComplete milestone\r\n this.endDomCompleteMilestone();\r\n }\r\n\r\n /**\r\n * Default react hook.\r\n *\r\n * note: don't delete it, as it has different arity than the original react hook, and some components call it\r\n * with arity=0\r\n *\r\n * @param prevProps - previous component props\r\n * @param prevState - previous component state\r\n * @param snapshot - \"snapshot\" returned by getSnapshotBeforeUpdate() in React life cycle\r\n */\r\n public componentDidUpdate(prevProps: Readonly = undefined,\r\n prevState: Readonly = undefined,\r\n snapshot: any = undefined): void {\r\n // End the domComplete milestone\r\n this.endDomCompleteMilestone();\r\n }\r\n\r\n /**\r\n * Default render function\r\n *\r\n * note: don't delete it, even if empty, as a bunch of code calls super.render()\r\n */\r\n public render(): any {\r\n logger.log(`Rendering ${(this.props as CommonExperienceProps).experienceName}. needsHydrate: ${canUseDOM() && window.needsHydrate}`);\r\n\r\n // End the initialized milestone, and start the domComplete milestone\r\n this.endInitializeMilestone();\r\n this.startDomCompleteMilestone();\r\n }\r\n\r\n /**\r\n * Marks the Time To Visually Ready and optionally mark perf ttvr for telemetry.\r\n * @param shouldMarkTelemetryTtvr - Flag to opt out from from telemetry ttvr marker\r\n */\r\n public markTimeToVisuallyReady(shouldMarkTelemetryTtvr: boolean): void {\r\n if (shouldMarkTelemetryTtvr) {\r\n markTtvr((this.props as CommonExperienceProps).experienceName);\r\n }\r\n\r\n this.endVisuallyReadyMilestone();\r\n }\r\n\r\n /**\r\n * Generate attributes for the mnsDashboard\r\n */\r\n protected mnsDashAttributes(): MnsCreatorDashboardAttributes {\r\n if (appEnvironment.ShowMnsCreatorDashboard) {\r\n const msnCreatorDashAttributes = {\r\n \"data-config-href\": this.props[\"data-config-href\"],\r\n \"data-experience-type\": this.props[\"data-experience-type\"]\r\n };\r\n return msnCreatorDashAttributes;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n /** Start the initialized perf timer, and mark the Initialized milestone start time */\r\n protected startInitializeMilestone(): void {\r\n this.initializedTracker.setStart();\r\n\r\n if ((this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate) {\r\n (this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate(ExperienceMilestoneEventTypes.initialized,\r\n this.initializedTracker.getStart());\r\n }\r\n }\r\n\r\n /** End the initialized perf timer, and mark the Initialized milestone end time */\r\n protected endInitializeMilestone(): void {\r\n if (this.initializedTracker.getEnd() !== -1) {\r\n return;\r\n }\r\n\r\n this.initializedTracker.setEnd();\r\n\r\n if ((this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate) {\r\n (this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate(ExperienceMilestoneEventTypes.initialized,\r\n undefined,\r\n this.initializedTracker.getEnd());\r\n }\r\n }\r\n\r\n /** Start the Visually Reader perf timer, and mark the VisuallyReady milestone start time */\r\n protected startVisuallyReadyMilestone(): void {\r\n this.visuallyReadyTracker.setStart();\r\n\r\n if ((this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate) {\r\n (this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate(ExperienceMilestoneEventTypes.visuallyReady,\r\n this.visuallyReadyTracker.getStart());\r\n }\r\n }\r\n\r\n /** End the Visually Reader perf timer, and mark the VisuallyReady milestone end time */\r\n protected endVisuallyReadyMilestone(): void {\r\n if (this.visuallyReadyTracker.getEnd() !== -1) {\r\n return;\r\n }\r\n\r\n this.visuallyReadyTracker.setEnd();\r\n\r\n if ((this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate) {\r\n (this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate(ExperienceMilestoneEventTypes.visuallyReady,\r\n undefined,\r\n this.visuallyReadyTracker.getEnd());\r\n }\r\n }\r\n\r\n /** Start the DomComplete perf timer, and mark the DomComplete milestone start time */\r\n protected startDomCompleteMilestone(): void {\r\n this.domCompleteTracker.setStart();\r\n\r\n if ((this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate) {\r\n (this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate(ExperienceMilestoneEventTypes.domComplete,\r\n this.domCompleteTracker.getStart());\r\n }\r\n }\r\n\r\n /** End the DomComplete perf timer, and mark the DomComplete milestone end time */\r\n protected endDomCompleteMilestone(): void {\r\n if (this.domCompleteTracker.getEnd() !== -1) {\r\n return;\r\n }\r\n\r\n this.domCompleteTracker.setEnd();\r\n\r\n if ((this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate) {\r\n (this.props as CommonExperienceProps).onExperienceMilestoneTimingUpdate(ExperienceMilestoneEventTypes.domComplete,\r\n undefined,\r\n this.domCompleteTracker.getEnd());\r\n }\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Time To Functional\r\n */\r\nexport const timeToFunctional: string = \"TTF\";\r\n\r\n/**\r\n * Time To Page Visible\r\n */\r\nexport const timeToPageVisible: string = \"TTPV\";\r\n\r\n/**\r\n * Time To Visually Ready\r\n */\r\nexport const timeToVisuallyReady: string = \"TTVR\";\r\n\r\n/**\r\n * Time To Video Start\r\n */\r\nexport const timeToVideoStart: string = \"TTVS\";","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { timeToFunctional, timeToVideoStart, timeToVisuallyReady } from \"./PerfMarkerConstants\";\r\n\r\nimport { perfMarker } from \"./PerfMarker\";\r\n\r\n/** Collection of marker names grouped by marker type */\r\nexport interface MarkerNames {\r\n /** Array of timeToFunctional names */\r\n TTF?: string[];\r\n\r\n /** Array of timeToVisualReady names */\r\n TTVR?: string[];\r\n}\r\n\r\nlet remainingMarkers: Set;\r\nlet remainingTtvrMarkers: Set;\r\n\r\nlet ttvrPromise: Promise<[string, number][]>;\r\nlet resolveTtvrCallback: (markers: [string, number][]) => void;\r\n\r\nlet perfMarkerPromise: Promise<[string, number][]>;\r\nlet perfMarkerResolveCallback: (markers: [string, number][]) => void;\r\n\r\nlet ttvsMarkerPromise: Promise<[string, number][]>;\r\nlet resolveTtvsCallback: (ttvs: [string, number][]) => void;\r\n\r\n/** The markers map. Key is the experience name, e.g. \"River\". Value is the number of milliseconds it took to reach that marker. */\r\nlet markers: Map = new Map();\r\n\r\nconst ttfPrefix: string = \"TTF.\";\r\nconst ttvrPrefix: string = \"TTVR.\";\r\nconst ttvsPrefix: string = \"TTVS.\";\r\n\r\nlet isSetMarkersCalled: boolean = false;\r\n\r\n/**\r\n * Saves the Time To Functional timestamp for the given marker and also marks the performance timeline.\r\n * If the same marker is added again, it overrides with the original marker.\r\n * @param name - The marker name\r\n * @param markTimeNA - To set -1 mark time for the TTF to resolve the dependency.\r\n * @param time - The elapsed time since window.performance.timing.navigationStart\r\n */\r\nexport function markTtf(name: string = \"\", markTimeNA: boolean = false, time: number = window.performance.now()): void {\r\n return setMark(ttfPrefix, name, markTimeNA, time);\r\n}\r\n\r\n/**\r\n * Saves the Time To Visually Ready timestamp for the given marker and also marks the performance timeline.\r\n * If the same marker is added again, it overrides with the original marker.\r\n * @param name - The marker name\r\n * @param markTimeNA - To set -1 mark time for the TTVR to resolve the dependency.\r\n * @param time - The elapsed time since window.performance.timing.navigationStart\r\n */\r\nexport function markTtvr(name: string = \"\", markTimeNA: boolean = false, time: number = window.performance.now()): void {\r\n return setMark(ttvrPrefix, name, markTimeNA, time);\r\n}\r\n\r\n/**\r\n * Helper that wraps the markTtvr call inside a request animation frame and setTimeout\r\n * with the idea that this will allow the experience time to render before setting the mark\r\n * @param name The marker name\r\n * @param markTimeNA To set -1 mark time for the TTVR to resolve the dependency\r\n */\r\nexport function markTtvrRaf(name: string = \"\", markTimeNA: boolean = false): void {\r\n window.requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n markTtvr(name, markTimeNA);\r\n }, 0);\r\n });\r\n}\r\n\r\n/**\r\n * Saves the Time to Video Start timestamp for the given marker and also marks the performance timeline.\r\n * If the same marker is added again, it overrides with the original marker.\r\n * @param name - The marker name\r\n * @param markTimeNA - To set -1 mark time for the TTVR to resolve the dependency.\r\n * @param time - The elapsed time since window.performance.timing.navigationStart\r\n */\r\nexport function markTtvs(name: string = \"\", markTimeNA: boolean = false, time: number = window.performance.now()): void {\r\n return setMark(ttvsPrefix, name, markTimeNA, time);\r\n}\r\n\r\n/**\r\n * Saves the timestamp for the given marker and also marks the performance timeline.\r\n * If the same marker is added again, it overrides with the original marker.\r\n * @param name - The marker name\r\n * @param markTimeNA - To set -1 mark time for the ttvr to resolve the dependency.\r\n * @param time - The elapsed time since window.performance.timing.navigationStart\r\n */\r\nfunction setMark(prefix: string, name: string, markTimeNA: boolean, time: number): void {\r\n if (!(name && name.length)) {\r\n return;\r\n }\r\n\r\n if (!(prefix && prefix.length)) {\r\n return;\r\n }\r\n\r\n const markerFullName = prefix + name;\r\n\r\n // To check if the marker exists then return.\r\n if (markers.get(markerFullName)) {\r\n return;\r\n }\r\n\r\n let existingMarker = performance.getEntriesByName && performance.getEntriesByName(markerFullName);\r\n let isMarkerSet = Boolean(existingMarker && existingMarker.length);\r\n\r\n if (!isMarkerSet) {\r\n perfMarker.singleMark(markerFullName);\r\n\r\n if (markTimeNA) {\r\n markers.set(markerFullName, -1);\r\n } else {\r\n markers.set(markerFullName, Math.round(time));\r\n }\r\n } else {\r\n markers.set(markerFullName, Math.round(existingMarker[0].startTime));\r\n }\r\n\r\n // Notify any callers waiting for TTVR reports\r\n if (remainingTtvrMarkers && remainingTtvrMarkers.delete(markerFullName) && remainingTtvrMarkers.size === 0 && resolveTtvrCallback) {\r\n resolveTtvrCallback(getTtvrMarkers());\r\n }\r\n\r\n // Notify any callers waiting for reports\r\n if (remainingMarkers && remainingMarkers.delete(markerFullName) && remainingMarkers.size === 0 && perfMarkerResolveCallback) {\r\n perfMarkerResolveCallback(getMarkers());\r\n }\r\n\r\n // Resolve TTVS if this is ttvs. TTVS only need one time to mark instead of multiple markers.\r\n if (prefix === ttvsPrefix && resolveTtvsCallback) {\r\n resolveTtvsCallback(getTtvsMarkers());\r\n }\r\n}\r\n\r\n/**\r\n * Sets the collection of primary perf markers to use for waitForAllPerfMarkers, waitForTtvr .\r\n * @param markerNames The collection of primary TTF and TTVR perf markers.\r\n */\r\nexport function setMarkers(markerNames: MarkerNames): void {\r\n remainingMarkers = getRemainingMarkers(markerNames);\r\n remainingTtvrMarkers = getRemainingMarkers(markerNames, \"TTVR\");\r\n\r\n if (resolveTtvrCallback && remainingTtvrMarkers.size === 0) {\r\n perfMarkerResolveCallback(getTtvrMarkers());\r\n }\r\n\r\n if (perfMarkerResolveCallback && remainingMarkers.size === 0) {\r\n perfMarkerResolveCallback(getMarkers());\r\n }\r\n\r\n isSetMarkersCalled = true;\r\n}\r\n\r\n/**\r\n * Determines whether setMarkers has been called.\r\n */\r\nexport function setMarkersCalled(): boolean {\r\n return isSetMarkersCalled;\r\n}\r\n\r\n/**\r\n * Waits for the all perf markers supplied to setMarkers() to be logged.\r\n * @returns A promise with all of the TTF and TTVR perf markers, including the overall page marker\r\n */\r\nexport function waitForAllPerfMarkers(): Promise<[string, number][]> {\r\n return waitForPerfMarkers();\r\n}\r\n\r\n/**\r\n * Waits for the TTVR markers supplied to setMarkers() to be logged.\r\n * @returns A promise with the TTVR perf markers, including the overall page TTVR marker\r\n */\r\nexport function waitForTtvr(): Promise<[string, number][]> {\r\n // If we have a promise, return it. It may already be completed.\r\n if (ttvrPromise) {\r\n return ttvrPromise;\r\n }\r\n\r\n if (remainingTtvrMarkers && remainingTtvrMarkers.size === 0) {\r\n return Promise.resolve(getTtvrMarkers());\r\n }\r\n\r\n // If the markers are not yet declared or are incomplete, set up a promise to resolve when they are all done.\r\n ttvrPromise = new Promise<[string, number][]>(resolve => {\r\n resolveTtvrCallback = resolve;\r\n });\r\n\r\n return ttvrPromise;\r\n}\r\n\r\n/**\r\n * Waits for the perf markers supplied to setMarkers() to be logged.\r\n * @returns A promise with all of the TTF and TTVR perf markers, including the overall page marker\r\n */\r\nfunction waitForPerfMarkers(): Promise<[string, number][]> {\r\n // If we have a promise, return it. It may already be completed.\r\n if (perfMarkerPromise) {\r\n return perfMarkerPromise;\r\n }\r\n\r\n if (remainingMarkers && remainingMarkers.size === 0) {\r\n return Promise.resolve(getMarkers());\r\n }\r\n\r\n // If the markers are not yet declared or are incomplete, set up a promise to resolve when they are all done.\r\n perfMarkerPromise = new Promise<[string, number][]>(resolve => {\r\n perfMarkerResolveCallback = resolve;\r\n });\r\n\r\n return perfMarkerPromise;\r\n}\r\n\r\n/**\r\n * Wait for the ttvs marker to be logged\r\n * @returns A promise with TTVS perf time in ms\r\n */\r\nexport function waitForTtvsMarker(): Promise<[string, number][]> {\r\n if (ttvsMarkerPromise) {\r\n return ttvsMarkerPromise;\r\n }\r\n\r\n ttvsMarkerPromise = new Promise<[string, number][]>(resolve => {\r\n resolveTtvsCallback = resolve;\r\n });\r\n\r\n return ttvsMarkerPromise;\r\n}\r\n\r\n/**\r\n * Returns array of TTF markers, including the page-level marker. For example:\r\n * [[\"TTF.Search\", 100], [\"TTF\", 100]]\r\n * @returns The array of markers\r\n */\r\nfunction getTtfMarkers(): [string, number][] {\r\n return getMarkersWithType(ttfPrefix, timeToFunctional);\r\n}\r\n\r\n/**\r\n * Returns array of TTVR markers, including the page-level marker. For example:\r\n * [[\"TTVR.Search\", 100], [\"TTVR.TopSites\", 100.123], [\"TTVR.River\", 100.504], [\"TTVR\", 100.504]]\r\n * @returns The array of markers\r\n */\r\nfunction getTtvrMarkers(): [string, number][] {\r\n return getMarkersWithType(ttvrPrefix, timeToVisuallyReady);\r\n}\r\n\r\n/**\r\n * Returns array of TTVS markers, including the page-level marker. For example:\r\n * [[\"TTVS.VideoContent\", 1200], [\"TTVS\", 1200]]\r\n * @returns The array of markers\r\n */\r\nfunction getTtvsMarkers(): [string, number][] {\r\n return getMarkersWithType(ttvsPrefix, timeToVideoStart);\r\n}\r\n\r\n/**\r\n * Returns array of a provided markers baesd on markerName, including the page-level marker.\r\n * @param markerPrefix the marker prefix for the markers\r\n * @param markerName the markerName for the marker\r\n * @returns The array of markers\r\n */\r\nfunction getMarkersWithType(markerPrefix: string, markerName: string) {\r\n const result: [string, number][] = [];\r\n let maxValue = 0;\r\n markers.forEach((value: number, key: string) => {\r\n if (key.startsWith(markerPrefix)) {\r\n result.push([key, value]);\r\n if (value > maxValue) {\r\n maxValue = value;\r\n }\r\n }\r\n });\r\n\r\n // Add the max, overall marker at the end\r\n result.push([markerName, maxValue]);\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Returns array of markers, including the page-level marker. For example:\r\n * Note: didn't add TTVS in getMarkers because TTVS only applies to specific page type and special cases.\r\n * It could be fired way after in the page cycle.\r\n * [[\"TTVR.Search\", 100], [\"TTVR.TopSites\", 100.123], [\"TTVR.River\", 100.504], [\"TTVR\", 100.504]]\r\n * @returns The array of markers\r\n */\r\nfunction getMarkers(): [string, number][] {\r\n const ttvrResults = getTtvrMarkers();\r\n const ttfResults = getTtfMarkers();\r\n const result: [string, number][] = [...ttvrResults, ...ttfResults];\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Returns markers yet to be set\r\n * @param markerNames The names of the markers to check. e.g. { TTVR: [\"River\", \"TopSites\"], TTF: [\"SearchBox\"] }\r\n * @param markerType The type of markers to return \"TTVR\", \"TTF\", or if undefined all\r\n * @returns The set of markers that have not yet been set.\r\n */\r\nfunction getRemainingMarkers(markerNames: MarkerNames, markerType?: string): Set {\r\n let result: Set = new Set();\r\n for (let markerName of flattenMarkerNames(markerNames, markerType)) {\r\n if (!markers.get(markerName)) {\r\n result.add(markerName);\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Put marker names into a expanded/flattened array [ \"TTVR.River\", \"TTVR.TopSites\", \"TTF.SearchBox\" ]\r\n * @param markerNames The names of the markers to check. e.g. { TTVR: [ \"River\", \"TopSites\" ], TTF: [ \"SearchBox\" ] }\r\n * @param markerType The type of markers to return \"TTVR\", \"TTF\", or if undefined all\r\n */\r\nfunction flattenMarkerNames(markerNames: MarkerNames, markerType: string): string[] {\r\n let ttvr: string[] = [];\r\n let ttf: string[] = [];\r\n\r\n if (markerNames && markerNames.TTVR && (!markerType || markerType === \"TTVR\")) {\r\n ttvr = markerNames.TTVR.map((n) => { return ttvrPrefix + n; });\r\n }\r\n\r\n if (markerNames && markerNames.TTF && (!markerType || markerType === \"TTF\")) {\r\n ttf = markerNames.TTF.map((n) => { return ttfPrefix + n; });\r\n }\r\n\r\n return [...ttvr, ...ttf];\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { Glyph, GlyphType } from \"@msnews/icon\";\r\n\r\nimport { IntraArticleComponentType } from \"./\";\r\nimport { KeyValueArray } from \"@msnews/core\";\r\n\r\n/**\r\n * Social media provider details interface\r\n */\r\ninterface SocialMediaProvider {\r\n apiUrl: string;\r\n attribution: string;\r\n name: string;\r\n}\r\n\r\n/**\r\n * Dictionary of social media provider configuration.\r\n */\r\nlet SocialMediaProviderConfig: KeyValueArray = [];\r\nSocialMediaProviderConfig[IntraArticleComponentType.Unknown] = { apiUrl: \"\", attribution: \"\", name: \"\" };\r\nSocialMediaProviderConfig[IntraArticleComponentType.FacebookEmbed] = { apiUrl: \"//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.5&appid=689384617806917\", attribution: \"Facebook Inc.\", name: \"Facebook\" };\r\nSocialMediaProviderConfig[IntraArticleComponentType.InstagramEmbed] = { apiUrl: \"//instagram.com/embed.js\", attribution: \"Instagram Inc.\", name: \"Instagram\" };\r\nSocialMediaProviderConfig[IntraArticleComponentType.TwitterEmbed] = { apiUrl: \"//platform.twitter.com/widgets.js\", attribution: \"Twitter Inc.\", name: \"Twitter\" };\r\n\r\n/**\r\n * Enumerates the available sharing option keys\r\n * @export\r\n */\r\nenum SocialMedia {\r\n Email = \"email\",\r\n Facebook = \"facebook\",\r\n Line = \"line\",\r\n LinkedIn = \"linkedin\",\r\n Skype = \"skype\",\r\n Twitter = \"twitter\",\r\n WhatsApp = \"whatsapp\"\r\n}\r\n\r\n/**\r\n * Possible target attribute to open social media linked pages\r\n */\r\nenum SocialMediaTarget {\r\n _blank = \"_blank\",\r\n _self = \"_self\",\r\n _parent = \"_parent\",\r\n _top = \"_top\",\r\n newWindow = \"newWindow\"\r\n}\r\n\r\n/**\r\n * A map of social media items and its config attributes\r\n * @export\r\n * @type {[key in SocialMedia]: SocialMediaItemConfigAttributes}\r\n */\r\ntype SocialMediaConfig = {[key in SocialMedia]: SocialMediaItemConfigAttributes};\r\n\r\n/**\r\n * The default configuration values for social media. Those can be overriden per experience\r\n * @export\r\n * @type {SocialMediaConfig}\r\n */\r\nconst SocialMediaDefaultConfig: SocialMediaConfig = {\r\n [SocialMedia.Email]: {\r\n ariaLabel: \"share via email\",\r\n backgroundColor: \"#0078D7\",\r\n color: \"white\",\r\n icon: Glyph.Mail,\r\n label: \"Mail\",\r\n target: SocialMediaTarget._self,\r\n url: \"mailto:?subject={title}&body=I thought you would be interested in this story I found on MSN: {url}\"\r\n },\r\n [SocialMedia.Facebook]: {\r\n ariaLabel: \"share on facebook\",\r\n backgroundColor: \"#4267B2\",\r\n color: \"white\",\r\n icon: Glyph.Facebook,\r\n label: \"Facebook\",\r\n target: SocialMediaTarget._blank,\r\n url: \"https://www.facebook.com/sharer.php?u={url}&t={title}\"\r\n },\r\n [SocialMedia.Line]: {\r\n ariaLabel: \"share on line\",\r\n backgroundColor: \"#00C300\",\r\n color: \"white\",\r\n icon: Glyph.Line,\r\n label: \"Line\",\r\n target: SocialMediaTarget._blank,\r\n url: \"https://social-plugins.line.me/lineit/share?url={url}\"\r\n },\r\n [SocialMedia.LinkedIn]: {\r\n ariaLabel: \"share on linkedin\",\r\n backgroundColor: \"#0083BE\",\r\n color: \"white\",\r\n icon: Glyph.LinkedIn,\r\n label: \"LinkedIn\",\r\n target: SocialMediaTarget._blank,\r\n url: \"https://www.linkedin.com/shareArticle?mini=true&url={url}&title={title}&source={refererUrl}\"\r\n },\r\n [SocialMedia.Skype]: {\r\n ariaLabel: \"share on skype\",\r\n backgroundColor: \"#33BFFC\",\r\n color: \"white\",\r\n icon: Glyph.Skype,\r\n label: \"Skype\",\r\n target: SocialMediaTarget._blank,\r\n url: \"https://web.skype.com/share?url={url}&flow_id={flowid}&source=msn\"\r\n },\r\n [SocialMedia.Twitter]: {\r\n ariaLabel: \"share on twitter\",\r\n backgroundColor: \"#20A2F2\",\r\n color: \"white\",\r\n icon: Glyph.Twitter,\r\n label: \"Twitter\",\r\n target: SocialMediaTarget._blank,\r\n url: \"https://twitter.com/share?url={url}&text={title}&original_referer={refererUrl}\"\r\n },\r\n [SocialMedia.WhatsApp]: {\r\n ariaLabel: \"share on whatsapp\",\r\n backgroundColor: \"#25D366\",\r\n color: \"white\",\r\n icon: Glyph.WhatsApp,\r\n label: \"WhatsApp\",\r\n target: SocialMediaTarget._blank,\r\n url: \"https://web.whatsapp.com/send?text={url}\"\r\n }\r\n};\r\n\r\n/**\r\n * The config attributed type for a given social media\r\n * @export\r\n */\r\ntype SocialMediaItemConfigAttributes = {\r\n /** Arial labe text */\r\n ariaLabel?: string,\r\n /** Attributes to be spread in the anchor tag element */\r\n attributes?: React.HTMLAttributes,\r\n /** Background color of the icon div */\r\n backgroundColor?: string,\r\n /** Foreground color of the icon div */\r\n color?: string,\r\n /** Icon glyph to override default value */\r\n icon?: GlyphType,\r\n /** Label text to override default value */\r\n label?: string,\r\n /** To be used in js window.open features param if target = newWindow */\r\n newWindowOptions?: any,\r\n /** telemetry click event should be handled by the caller using this callback */\r\n newWindowTelemetryCall?: (event: any) => void,\r\n /** ocid to be appended in the shared link */\r\n ocid?: string,\r\n /** target to be placed in anchor tag. newWindow has a customized js method that can make use of newWindowOptions attribute */\r\n target?: SocialMediaTarget,\r\n /** Share url to be hard overriden */\r\n url?: string\r\n};\r\n\r\nexport {\r\n SocialMedia,\r\n SocialMediaProvider,\r\n SocialMediaProviderConfig,\r\n SocialMediaConfig,\r\n SocialMediaDefaultConfig,\r\n SocialMediaItemConfigAttributes,\r\n SocialMediaTarget\r\n };\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { PopOverHandledProps, PopOverProps, PopOverUnhandledProps } from \"./PopOver.props\";\r\n\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { DesignSystemConsumer } from \"@microsoft/fast-jss-manager-react\";\r\nimport { Direction } from \"@microsoft/fast-web-utilities\";\r\nimport Foundation from \"@microsoft/fast-components-foundation-react\";\r\nimport { HandledPropsKeys } from \"@msnews/core\";\r\nimport React from \"react\";\r\nimport ReactDOM from \"react-dom\";\r\nimport Tabbable from \"tabbable\";\r\nimport { keyCodeTab } from \"@microsoft/fast-web-utilities\";\r\n\r\ninterface PositionStyles {\r\n /** Top offset, in px */\r\n top: number;\r\n\r\n /** Left offset, in px */\r\n left?: number;\r\n\r\n /** Right offset, in px */\r\n right?: number;\r\n}\r\n\r\n/**\r\n * PopOver component\r\n * @class - PopOver\r\n * @classdesc - The PopOver component. Renders a popover menu on a new portal. Position to be defined by top/left props\r\n * @default\r\n */\r\nclass PopOver extends Foundation {\r\n /**\r\n * The Pop Over handled prop contract\r\n * Describes the object that enumerates all handled props for a component. This\r\n * object includes all props that can in some way consumed or manipulated by component\r\n * code.\r\n * @protected\r\n * @type { HandledPropsKeys }\r\n */\r\n protected handledProps: HandledPropsKeys = {\r\n anchor: undefined,\r\n autoFlipX: undefined,\r\n autoFocus: undefined,\r\n children: undefined,\r\n enable: undefined,\r\n left: undefined,\r\n managedClasses: undefined,\r\n offset: undefined,\r\n onDismiss: undefined,\r\n staticPosition: undefined,\r\n top: undefined,\r\n zIndex: undefined\r\n };\r\n\r\n /** Reference for the PopOver div element */\r\n private popOverRef: React.RefObject;\r\n\r\n constructor(props: PopOverProps) {\r\n super(props);\r\n this.popOverRef = React.createRef();\r\n this.state = {\r\n width: 0,\r\n height: 0\r\n };\r\n }\r\n\r\n /**\r\n * Component did mount\r\n */\r\n public componentDidMount(): void {\r\n if (this.popOverRef && this.popOverRef.current) {\r\n const { width, height } = this.popOverRef.current.getBoundingClientRect();\r\n this.setState({ width, height });\r\n } else if (!this.props.enable && this.state.width && this.state.height) {\r\n this.setState({width: 0, height: 0});\r\n }\r\n }\r\n\r\n /**\r\n * Component has updated\r\n */\r\n public componentDidUpdate(): void {\r\n if (this.popOverRef && this.popOverRef.current) {\r\n if (this.props.autoFocus) {\r\n this.popOverRef.current.focus();\r\n }\r\n const { width, height } = this.popOverRef.current.getBoundingClientRect();\r\n if (width !== this.state.width || height !== this.state.height) {\r\n this.setState({ width, height });\r\n }\r\n } else if (!this.props.enable && this.state.width && this.state.height) {\r\n this.setState({width: 0, height: 0});\r\n }\r\n }\r\n\r\n /**\r\n * Component renderer\r\n * @public\r\n * @method\r\n * @returns {JSX.Element} the popover component rendered in a new portal\r\n */\r\n public render(): JSX.Element {\r\n const { enable, managedClasses, staticPosition, zIndex } = this.props;\r\n if (!enable) {\r\n return null;\r\n }\r\n let result = (null);\r\n const zIndexStyle = zIndex != undefined ? {zIndex} : {};\r\n if (!this.popOverRef || !this.popOverRef.current) {\r\n result = (\r\n \r\n {this.props.children}\r\n \r\n );\r\n } else {\r\n result = (\r\n \r\n {({ direction }: DesignSystem) => (\r\n \r\n {this.props.children}\r\n \r\n )}\r\n \r\n );\r\n }\r\n\r\n return staticPosition ? result : ReactDOM.createPortal(result, document.body);\r\n }\r\n\r\n /**\r\n * Event handler for tab event\r\n */\r\n private tabEventHandler = (e: React.KeyboardEvent) => {\r\n if (e.keyCode === keyCodeTab\r\n && this.props.anchor\r\n && this.popOverRef.current.contains(document.activeElement)) {\r\n const tabbable: HTMLElement[] = Tabbable(this.popOverRef.current);\r\n const {onDismiss = () => null, anchor} = this.props;\r\n if (e.shiftKey && e.target === tabbable[0]) {\r\n // focus on anchor if shift+tab is pressed on the first tabbable element\r\n anchor.focus();\r\n onDismiss(e);\r\n e.preventDefault();\r\n } else if (!e.shiftKey && e.target === tabbable[tabbable.length - 1]) {\r\n // focus on the next tabbable from anchor if tab is pressed on the last tabbable element\r\n anchor.focus();\r\n onDismiss(e);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * calculate the placement style for popover\r\n */\r\n private getPlacementStyle(pageDirection: Direction): PositionStyles {\r\n let { left, top, offset, anchor } = this.props;\r\n const { autoFlipX } = this.props;\r\n if (anchor && left === undefined && top === undefined) {\r\n const position = this.determinePosition();\r\n left = position.left;\r\n top = position.top;\r\n offset = position.offset;\r\n }\r\n const { width, height } = this.state;\r\n const windowWidth = window.innerWidth;\r\n const documentHeight = window.document && window.document.documentElement && window.document.documentElement.offsetHeight;\r\n\r\n if (documentHeight && top + height > documentHeight) {\r\n top = documentHeight - height - offset;\r\n }\r\n // Styles for displaying on left of origin\r\n const displayOnLeft: PositionStyles = {\r\n top,\r\n right: windowWidth - left\r\n };\r\n\r\n // Styles for displaying on right of origin\r\n const displayOnRight: PositionStyles = {\r\n top,\r\n left: left + offset\r\n };\r\n\r\n // Prioritise displaying on right for LTR, on left for RTL\r\n const [displayOnPrioritySide, displayOnNonPrioritySide] =\r\n pageDirection === Direction.rtl ? [displayOnLeft, displayOnRight] : [displayOnRight, displayOnLeft];\r\n\r\n // Determine which directions have enough space to display full width\r\n const canFitPrioritySide = (displayOnPrioritySide.left || displayOnPrioritySide.right) + width < windowWidth;\r\n const canFitNonPrioritySide = (displayOnNonPrioritySide.left || displayOnNonPrioritySide.right) + width < windowWidth;\r\n\r\n // Return non-priority if auto-flip is enabled, and only the priority direction doesn't have space\r\n return autoFlipX && !canFitPrioritySide && canFitNonPrioritySide ? displayOnNonPrioritySide : displayOnPrioritySide;\r\n }\r\n\r\n /**\r\n * determine position based on anchor position\r\n */\r\n private determinePosition = (): {top: number, left: number, offset: number} => {\r\n const { anchor } = this.props;\r\n if (anchor) {\r\n const { top, left, width } = anchor.getBoundingClientRect();\r\n return { top: top + window.scrollY, left: left + window.scrollX, offset: width };\r\n }\r\n return { top: window.scrollY, left: window.scrollX, offset: 0 };\r\n }\r\n}\r\n\r\nexport default PopOver;\r\nexport * from \"./PopOver.props\";\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ComponentStyles } from \"@microsoft/fast-jss-manager\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { PopOverClassNameContract } from \"./PopOver.classnames\";\r\nimport { ZIndex } from \"@msnews/core\";\r\n\r\n/**\r\n * The main JSS stylesheet for the popover component\r\n */\r\nexport const PopOverStyles: ComponentStyles = {\r\n popOver: {\r\n \"animation-duration\": \"0.367s\",\r\n \"animation-fill-mode\": \"both\",\r\n \"animation-name\": \"fadeIn, slideIn\",\r\n \"animation-timing-function\": \"cubic-bezier(0.1, 0.9, 0.2, 1)\",\r\n position: \"absolute\",\r\n \"z-index\": `${ZIndex.Flyout}`,\r\n \"&:focus\": {\r\n outline: \"none\"\r\n }\r\n },\r\n popOverPlaceholder: {\r\n left: \"50%\",\r\n top: \"50%\",\r\n position: \"absolute\",\r\n visibility: \"hidden\"\r\n },\r\n \"@keyframes fadeIn\": {\r\n from: { opacity: 0 },\r\n to: { opacity: 1 }\r\n },\r\n \"@keyframes slideIn\": {\r\n from: { transform: \"translate3d(0px, -10px, 0px)\" },\r\n to: { transform: \"translate3d(0px, 0px, 0px)\" }\r\n }\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport BasePopOver, {\r\n PopOverHandledProps as BasePopOverHandledProps,\r\n PopOverProps as BasePopOverProps,\r\n PopOverManagedClasses,\r\n PopOverUnhandledProps\r\n} from \"./PopOver\";\r\nimport manageJss, { ManagedJSSProps } from \"@microsoft/fast-jss-manager-react\";\r\n\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { PopOverClassNameContract } from \"./PopOver.classnames\";\r\nimport { PopOverStyles } from \"./PopOver.styles\";\r\nimport { Subtract } from \"utility-types\";\r\n\r\n/*\r\n * The type returned by manageJss type is very complicated so we'll let the\r\n * compiler infer the type instead of re-declaring just for the package export\r\n */\r\n/* tslint:disable-next-line:typedef */\r\nconst PopOver = manageJss(PopOverStyles)(BasePopOver);\r\ntype PopOver = InstanceType;\r\n\r\n// Create a valid JSS managed interface that doesn't require managed classes which are provided by the manageJSS HOC\r\ninterface PopOverHandledProps\r\n extends Subtract {}\r\n\r\n// Create type for manageJSS HOC styled instance we are exporting\r\ntype PopOverProps = ManagedJSSProps<\r\n BasePopOverProps,\r\n PopOverClassNameContract,\r\n DesignSystem\r\n>;\r\n\r\n// Export everything a user might need from this index file\r\nexport {\r\n PopOver,\r\n PopOverProps,\r\n PopOverClassNameContract,\r\n PopOverHandledProps,\r\n PopOverUnhandledProps\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Enum to set standardized z-index values.\r\n * @export\r\n * @enum ZIndex\r\n * // EXAMPLE:\r\n * .block {\r\n * z-index: ZIndex.Neutral;\r\n * }\r\n *\r\n * BACKGROUND:\r\n * Providing this ramp ensures that z-index usage is not arbitrary.\r\n * Adequate room is left in each block for additional levels to be added if needed.\r\n *\r\n * USAGE:\r\n * 1100 (CookieWall): Use for Cookie wall(Compliance).\r\n * 900's (dialog): Use for Dialog component stack.\r\n * 700's (flyout): Use for all other flyout elements.\r\n * 500's (nav): Use for navigational elements.\r\n * 300's (over): Use for elements that need to be raised more out of the normal flow.\r\n * 100's (above): Use for elements that need to be raised out of the normal flow.\r\n * 1 (neutral): Common z-index value for elements that need to be above baseline.\r\n * 0 (default): Default browser element z-index (baseline).\r\n * -1 (below): Use for elements that need to live below the normal flow of the document.\r\n * -2 (buried): Reserved for lowest elements in the stack.\r\n *\r\n * OTHER GUIDANCE:\r\n * Easily increment within a block by adding an integer like the below example.\r\n * Consider a scenario where you need to increase something just above the navigation level:\r\n *\r\n * .block {\r\n * z-index: `${ZIndex.Nav + 1}`;\r\n * }\r\n *\r\n * You may also find it useful to increment by other values in the case where you are within a given stacking context.\r\n *\r\n * Recommended reading: https://philipwalton.com/articles/what-no-one-told-you-about-z-index/\r\n *\r\n * Note: If you have a reason to use a value above CookieWall, Make sure it is not causing a compliance violation.\r\n */\r\nexport enum ZIndex {\r\n CookieWall = 1100,\r\n Dialog = 900,\r\n Flyout = 700,\r\n Overlay = 600,\r\n Nav = 500,\r\n Over = 300,\r\n Above = 100,\r\n Neutral = 1,\r\n Default = 0,\r\n Below = -1,\r\n Buried = -2\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * The base URL for loading CMS images via CDN. Follows the format: https://[host]/tenant/amp/entityid/.\r\n * The content ID and image service parameters can be appended to the end to form the final URL.\r\n */\r\nexport const ImageServiceConfig = {\r\n \"prod\": \"https://img-s-msn-com.akamaized.net/tenant/amp/entityid/\"\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n CardContextMenu as BaseCardContextMenu,\r\n CardContextMenuHandledProps as BaseCardContextMenuHandledProps,\r\n CardContextMenuProps as BaseCardContextMenuProps,\r\n CardContextMenuUnHandledProps,\r\n CardContextMenusCssClassesManagedClasses\r\n} from \"./CardContextMenu\";\r\nimport manageJss, { ManagedJSSProps } from \"@microsoft/fast-jss-manager-react\";\r\n\r\nimport { CardContextMenuClassNameContract } from \"./CardContextMenu.classnames\";\r\nimport { CardContextMenuItem } from \"./CardContextMenu.props\";\r\nimport { CardContextMenuStyles } from \"./CardContextMenu.style\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { Subtract } from \"utility-types\";\r\n\r\n/*\r\n * The type returned by manageJss type is very complicated so we'll let the\r\n * compiler infer the type instead of re-declaring just for the package export\r\n */\r\n/* tslint:disable-next-line:typedef */\r\nconst CardContextMenu = manageJss(CardContextMenuStyles)(BaseCardContextMenu);\r\ntype CardContextMenu = InstanceType;\r\n\r\n/* tslint:disable-next-line:interface-name */\r\ninterface CardContextMenuHandledProps\r\n extends Subtract {}\r\ntype CardContextMenuProps = ManagedJSSProps<\r\n BaseCardContextMenuProps,\r\n CardContextMenuClassNameContract,\r\n DesignSystem\r\n>;\r\n\r\nexport {\r\n CardContextMenu,\r\n CardContextMenuClassNameContract,\r\n CardContextMenuHandledProps,\r\n CardContextMenuProps,\r\n CardContextMenuUnHandledProps,\r\n CardContextMenuItem\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { applyLocalizedProperty, toPx } from \"@microsoft/fast-jss-utilities\";\r\nimport {\r\n highContrastSelected,\r\n neutralFillActive,\r\n neutralFillHover,\r\n neutralFillRest,\r\n neutralOutlineActive,\r\n neutralOutlineHover,\r\n neutralOutlineRest\r\n}\r\n from \"@microsoft/fast-components-styles-msft\";\r\n\r\nimport { CardContextMenuClassNameContract } from \"./CardContextMenu.classnames\";\r\nimport { ComponentStyles } from \"@microsoft/fast-jss-manager\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\n\r\nexport const CardContextMenuStyles: ComponentStyles = (config: DesignSystem) => {\r\n return {\r\n settingButton: {\r\n height: \"100%\",\r\n width: \"100%\",\r\n border: \"none\",\r\n background: \"none\",\r\n cursor: \"pointer\",\r\n outline: \"none\",\r\n padding: \"0\",\r\n\r\n \"&:focus\": {\r\n border: `${toPx(config.outlineWidth)} dotted`,\r\n \"border-color\": neutralOutlineActive\r\n }\r\n },\r\n settingButtonIcon: {\r\n fill: neutralOutlineHover,\r\n height: \"24px\",\r\n width: \"24px\"\r\n },\r\n contextMenuItem: {\r\n display: \"flex\",\r\n cursor: \"pointer\",\r\n border: `${toPx(config.outlineWidth)} solid transparent`, // Reserve space for hover border\r\n height: \"30px\",\r\n margin: \"0\",\r\n padding: `0px 12px 0px`,\r\n \"user-select\": \"none\",\r\n \"&:focus, &:hover\": {\r\n background: neutralFillHover,\r\n \"border-color\": neutralOutlineHover,\r\n ...highContrastSelected\r\n },\r\n \"&:active\": {\r\n background: neutralFillActive\r\n }\r\n },\r\n contextMenuItem_contentRegion: {\r\n display: \"flex\",\r\n \"align-items\": \"center\"\r\n },\r\n contextMenuItem_image: {\r\n [applyLocalizedProperty(\"margin-right\", \"margin-left\", config.direction)]: \"8px\"\r\n },\r\n contextMenu: {\r\n \"box-shadow\": \"none\",\r\n padding: \"0\",\r\n width: \"145px\",\r\n background: neutralFillRest,\r\n border: `${toPx(config.outlineWidth)} solid`,\r\n \"border-color\": neutralOutlineRest\r\n }\r\n };\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { CardContextMenuHandledProps, CardContextMenuProps, CardContextMenuUnHandledProps } from \"./CardContextMenu.props\";\r\nimport { ContextMenu, ContextMenuItem } from \"@microsoft/fast-components-react-msft\";\r\n\r\nimport Foundation from \"@microsoft/fast-components-foundation-react\";\r\nimport { HandledPropsKeys } from \"@msnews/core\";\r\nimport { Icon } from \"@msnews/icon\";\r\nimport { More } from \"@edge-web-ui/news-icons\";\r\nimport { PopOver } from \"@msnews/pop-over\";\r\nimport React from \"react\";\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\nimport { isNil } from \"lodash-es\";\r\nimport { keyCodeEscape } from \"@microsoft/fast-web-utilities\";\r\n\r\ninterface CardContextMenuState {\r\n menuOpened: boolean,\r\n dropDownLocation?: {\r\n top?: number,\r\n left?: number,\r\n offset?: number\r\n }\r\n}\r\n\r\n/**\r\n * The component to render the context menu\r\n */\r\nclass CardContextMenu extends Foundation {\r\n /**\r\n * handled props for card context menu\r\n * @protected\r\n * @type { HandledPropsKeys}\r\n */\r\n protected handledProps: HandledPropsKeys = {\r\n managedClasses: undefined,\r\n menuItems: undefined,\r\n enabled: undefined,\r\n buttonLabel: undefined,\r\n positionOffset: undefined,\r\n telemetryTag: undefined,\r\n zIndex: undefined\r\n };\r\n\r\n /**\r\n * Reference to Container to set/unset focus\r\n * @private\r\n * @type { React.RefObject}\r\n */\r\n private containerRef: React.RefObject;\r\n\r\n /**\r\n * Reference to menu to set/unset focus\r\n * @private\r\n * @type { React.RefObject}\r\n */\r\n private menuRef: React.RefObject;\r\n\r\n /**\r\n * Reference to anchor button\r\n * @private\r\n * @type { React.RefObject}\r\n */\r\n private readonly buttonRef: React.RefObject;\r\n\r\n /**\r\n * Constructor Function for the CardContextMenu\r\n */\r\n public constructor(props: CardContextMenuHandledProps) {\r\n super(props);\r\n this.state = {\r\n menuOpened: false\r\n };\r\n this.containerRef = React.createRef();\r\n this.menuRef = React.createRef();\r\n this.buttonRef = React.createRef();\r\n }\r\n\r\n /**\r\n * Component did mount lifecycle event\r\n * @method\r\n */\r\n public componentDidMount(): void {\r\n if (canUseDOM()) {\r\n document.addEventListener(\"click\", this.handleUnfocus, false);\r\n document.addEventListener(\"keydown\", this.handleUnfocus, false);\r\n }\r\n }\r\n\r\n /**\r\n * Component did update lifecycle event\r\n * @method\r\n */\r\n public componentDidUpdate(): void {\r\n if (this.state.menuOpened) {\r\n this.menuRef.current.focus();\r\n }\r\n }\r\n\r\n /**\r\n * Component will unmount lifecycle event\r\n * @method\r\n */\r\n public componentWillUnmount(): void {\r\n if (canUseDOM()) {\r\n document.removeEventListener(\"click\", this.handleUnfocus, false);\r\n document.removeEventListener(\"keydown\", this.handleUnfocus, false);\r\n }\r\n }\r\n\r\n /**\r\n * Renders the component\r\n * @method\r\n * @returns {JSX.Element} The Card Context Menu JSX Element\r\n */\r\n public render(): JSX.Element {\r\n const { enabled, managedClasses, menuItems = [], telemetryTag } = this.props;\r\n if (!enabled || !menuItems.length) {\r\n return (null);\r\n }\r\n\r\n const { menuContainer, settingButton, settingButtonIcon } = managedClasses;\r\n\r\n return (\r\n
\r\n this.onSettingClick(e)}\r\n aria-label={this.props.buttonLabel}\r\n ref={this.buttonRef}\r\n {...telemetryTag}\r\n >\r\n \r\n \r\n {this.renderPopOver()}\r\n
\r\n );\r\n }\r\n\r\n /**\r\n * Renders the pop over menu\r\n * @method\r\n * @returns {JSX.Element} The pop over menu JSX Element\r\n */\r\n private renderPopOver(): JSX.Element {\r\n const { menuOpened, dropDownLocation } = this.state;\r\n const enabled = menuOpened && dropDownLocation && !isNil(dropDownLocation.left) && !isNil(dropDownLocation.top);\r\n const closeOnEscape = (e: React.KeyboardEvent) => e.keyCode === keyCodeEscape && this.closeMenu();\r\n\r\n return (\r\n \r\n
\r\n \r\n {this.renderContextMenu()}\r\n \r\n
\r\n
\r\n );\r\n }\r\n\r\n /**\r\n * Renders the context menu items\r\n * @method\r\n * @returns {JSX.Element} The pcontext menu items JSX Element\r\n */\r\n private renderContextMenu(): JSX.Element[] {\r\n const { menuItems } = this.props;\r\n const { contextMenuItem, contextMenuItem_contentRegion, contextMenuItem_image } = this.props.managedClasses;\r\n return menuItems.map(itemProps => (\r\n this.onMenuItemClick(e, itemProps.onSelect)}>\r\n
\r\n {itemProps.icon && (\r\n )}\r\n {itemProps.text}\r\n
\r\n \r\n ));\r\n }\r\n\r\n /**\r\n * Handles unfocusing the Context Menu\r\n * @method\r\n */\r\n private handleUnfocus = (e: Event) => {\r\n const buttonContainerContainsNode = (node: Node) => !this.containerRef.current || this.containerRef.current.contains(node);\r\n // Can't put ref on the PopOver react element, so we attach to a ref div and check its immediate parent\r\n // Must check parent because focus goes to PopOver, which is outside menuRef (otherwise menu closes when you try tab to it)\r\n const menuPopoverContainsNode = (node: Node) => !this.menuRef.current || this.menuRef.current.parentNode.contains(node);\r\n\r\n if (e.target && !buttonContainerContainsNode(e.target as Node) && !menuPopoverContainsNode(e.target as Node)) {\r\n this.closeMenu();\r\n }\r\n }\r\n\r\n /**\r\n * Handles closing the menu\r\n * @method\r\n */\r\n private closeMenu = (): void => {\r\n this.setState({ menuOpened: false });\r\n }\r\n\r\n /**\r\n * Handles the click on the menuitems\r\n * @method\r\n */\r\n private onMenuItemClick(event: any, onSelectCallback: (e) => void): void {\r\n if (onSelectCallback) {\r\n onSelectCallback(event);\r\n }\r\n this.closeMenu();\r\n }\r\n\r\n /**\r\n * Handles the click on the settings button to show the context menu\r\n * @method\r\n */\r\n private onSettingClick(e: any): void {\r\n const posOffset = this.props.positionOffset;\r\n const offsetX = posOffset ? posOffset.x : 0;\r\n const offsetY = posOffset ? posOffset.y : 0;\r\n\r\n let dropDownLocation = {};\r\n if (e.target) {\r\n const { top, left, width } = e.target.getBoundingClientRect();\r\n dropDownLocation = { top: top + offsetY + window.scrollY, left: left + offsetX + window.scrollX, offset: width };\r\n }\r\n this.setState({ menuOpened: !this.state.menuOpened, dropDownLocation });\r\n }\r\n}\r\n\r\nexport { CardContextMenu as CardContextMenu };\r\nexport * from \"./CardContextMenu.props\";","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { DesignSystem, applyTypeRampConfig, neutralForegroundRest } from \"@microsoft/fast-components-styles-msft\";\r\nimport { applyLocalizedProperty, toPx } from \"@microsoft/fast-jss-utilities\";\r\n\r\nimport { ButtonClassNameContract } from \"@microsoft/fast-components-class-name-contracts-msft\";\r\nimport { ComponentStyles } from \"@microsoft/fast-jss-manager\";\r\nimport { SocialMediaIconClassNameContract } from \"./SocialMediaIcon.classnames\";\r\n\r\n/** Value for border radius on icons */\r\nconst borderRadiusIcons = 2;\r\n\r\n/** icon height */\r\nconst iconHeight = 40;\r\n\r\n/** icon width */\r\nconst iconWidth = 40;\r\n\r\n/** label width */\r\nconst labelWidth = 60;\r\n\r\n/**\r\n * The JSS stylesheet for the social media icon\r\n * @type {ComponentStyles}\r\n * @param {DesignSystem} config - The design system configuration interface\r\n */\r\nexport const SocialMediaIconStyles: ComponentStyles = (config: DesignSystem) => {\r\n return {\r\n iconContainer: {\r\n \"border-radius\": toPx(borderRadiusIcons),\r\n height: toPx(iconHeight),\r\n width: toPx(iconWidth),\r\n \"line-height\": toPx(iconHeight),\r\n position: \"relative\",\r\n \"&:hover\": {\r\n cursor: \"pointer\"\r\n }\r\n },\r\n iconImage: {\r\n bottom: \"0\",\r\n left: \"0\",\r\n margin: \"auto\",\r\n position: \"absolute\",\r\n right: \"0\",\r\n top: \"0\"\r\n },\r\n iconLabel: {\r\n \"&&\": {\r\n ...applyTypeRampConfig(\"t8\"),\r\n \"line-height\": \"20px\",\r\n \"text-align\": \"center\",\r\n [applyLocalizedProperty(\"margin-left\", \"margin-right\", config.direction)]: toPx(-(labelWidth - iconHeight) / 2),\r\n \"margin-top\": \"4px\",\r\n padding: \"3px 0\",\r\n width: toPx(labelWidth)\r\n }\r\n }\r\n };\r\n};\r\n\r\n/** style to override button existing style */\r\nexport const ButtonStyle: Partial> = (config: DesignSystem) => {\r\n return {\r\n button__justified: {\r\n \"text-decoration\": \"none\",\r\n height: \"inherit\",\r\n \"min-width\": \"unset\",\r\n [applyLocalizedProperty(\"padding-left\", \"padding-right\", config.direction)]: toPx((labelWidth - iconHeight) / 2),\r\n \"&:focus\": {\r\n \"outline\": `1px solid ${neutralForegroundRest(config)}`\r\n }\r\n }\r\n };\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n SocialMediaIconHandledProps as BaseComponentHandledProps,\r\n SocialMediaIconProps as BaseComponentProps,\r\n SocialMediaIconManagedClasses,\r\n SocialMediaIconUnHandledProps\r\n} from \"./SocialMediaIcon.props\";\r\nimport manageJss, { ManagedJSSProps } from \"@microsoft/fast-jss-manager-react\";\r\n\r\nimport { SocialMediaIcon as BaseComponent } from \"./SocialMediaIcon\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { SocialMediaIconClassNameContract } from \"./SocialMediaIcon.classnames\";\r\nimport { SocialMediaIconStyles } from \"./SocialMediaIcon.styles\";\r\nimport { Subtract } from \"utility-types\";\r\n\r\n/*\r\n * The type returned by manageJss type is very complicated so we'll let the\r\n * compiler infer the type instead of re-declaring just for the package export\r\n */\r\n/* tslint:disable-next-line:typedef */\r\nconst SocialMediaIcon = manageJss(SocialMediaIconStyles)(BaseComponent);\r\ntype SocialMediaIcon = InstanceType;\r\n\r\n// Create a valid JSS managed interface that doesn't require managed classes which are provided by the manageJSS HOC\r\ninterface SocialMediaIconHandledProps extends Subtract { }\r\n\r\n// Create type for manageJSS HOC styled instance we are exporting\r\ntype SocialMediaIconProps = ManagedJSSProps;\r\n\r\n// Export everything a user might need from this index file\r\nexport {\r\n SocialMediaIcon,\r\n SocialMediaIconProps,\r\n SocialMediaIconClassNameContract,\r\n SocialMediaIconHandledProps,\r\n SocialMediaIconUnHandledProps\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { Button, ButtonAppearance, Label } from \"@microsoft/fast-components-react-msft\";\r\nimport {\r\n SharingHelper,\r\n SocialMediaDefaultConfig,\r\n SocialMediaItemConfigAttributes,\r\n SocialMediaTarget\r\n} from \"@msnews/views-helpers\";\r\nimport {\r\n SocialMediaIconHandledProps,\r\n SocialMediaIconProps,\r\n SocialMediaIconUnHandledProps\r\n} from \"./SocialMediaIcon.props\";\r\n\r\nimport { ButtonStyle } from \"./SocialMediaIcon.styles\";\r\nimport Foundation from \"@microsoft/fast-components-foundation-react\";\r\nimport { HandledPropsKeys } from \"@msnews/core\";\r\nimport { Icon } from \"@msnews/icon\";\r\nimport React from \"react\";\r\nimport { merge } from \"lodash-es\";\r\n\r\n/**\r\n * Social medial icon component\r\n * @class - The Social Media Icon class\r\n * @classdesc - Renders the visual Social Media Icon used to share links without major social media solutions.\r\n * @export\r\n * @default\r\n */\r\nexport class SocialMediaIcon extends Foundation {\r\n /**\r\n * Social media icon handled props contract\r\n * @protected\r\n * @type { HandledPropsKeys }\r\n */\r\n protected handledProps: HandledPropsKeys = {\r\n managedClasses: undefined,\r\n socialMedia: undefined,\r\n contentUrl: undefined,\r\n contentTitle: undefined,\r\n hideLabel: undefined,\r\n socialMediaItemConfigOverride: undefined\r\n };\r\n\r\n /**\r\n * Render social media icon\r\n *\r\n * @public\r\n * @return {JSX.Element}\r\n */\r\n public render(): JSX.Element {\r\n const { managedClasses, contentUrl, contentTitle, hideLabel, socialMedia, socialMediaItemConfigOverride } = this.props;\r\n const itemConfig = merge({}, SocialMediaDefaultConfig[socialMedia], socialMediaItemConfigOverride);\r\n if (!itemConfig) {\r\n return null;\r\n }\r\n\r\n const shareUrl = SharingHelper.getSocialMediaShareUrl(socialMedia, contentUrl, contentTitle, itemConfig.ocid, itemConfig.url);\r\n if (!shareUrl) {\r\n return null;\r\n }\r\n\r\n const target = itemConfig.target.toString();\r\n const targetRelatedAtributes = target === SocialMediaTarget.newWindow ?\r\n { onClick: (event: any) => this.onClickNewWindow(event, shareUrl, itemConfig.newWindowOptions, itemConfig.newWindowTelemetryCall), role: \"button\", \"data-customhandled\": true } :\r\n { href: shareUrl, target: target };\r\n\r\n return (\r\n \r\n );\r\n }\r\n\r\n /**\r\n * Handles custom on click when targeting new windows\r\n * @public\r\n * @return {JSX.Element}\r\n */\r\n private onClickNewWindow = (event: any, shareUrl: string, newWindowOptions: any, newWindowTelemetryCall: (event: any) => void): void => {\r\n SharingHelper.openNewWindow(event, shareUrl, newWindowOptions);\r\n if (newWindowTelemetryCall) {\r\n newWindowTelemetryCall(event);\r\n }\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Shallow compare of two objects.\r\n * Compares reference and primitive values of both object's key-value pairs\r\n *\r\n * @param a\r\n * @param b\r\n * @returns {bool} result of comparison.\r\n */\r\nexport function ShallowCompare(a: Object, b: Object): boolean {\r\n for (let key in a) {\r\n if (!(key in b) || a[key] !== b[key]) {\r\n return false;\r\n }\r\n }\r\n\r\n for (let key in b) {\r\n if (!(key in a) || a[key] !== b[key]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { CSSRules, ComponentStyleSheet, ComponentStyles } from \"@microsoft/fast-jss-manager\";\r\nimport {\r\n DesignSystem,\r\n DesignSystemDefaults,\r\n applyAcrylicMaterial,\r\n applyTypeRampConfig,\r\n fontWeight,\r\n neutralForegroundRest\r\n} from \"@microsoft/fast-components-styles-msft\";\r\nimport { applyLocalizedProperty, toPx } from \"@microsoft/fast-jss-utilities\";\r\nimport { get, memoize } from \"lodash-es\";\r\n\r\nimport { DialogClassNameContract } from \"@microsoft/fast-components-react-base\";\r\nimport { ShareDialogClassNameContract } from \"./ShareDialog.classnames\";\r\nimport { ZIndex } from \"@msnews/core\";\r\nimport { canUseDOM } from \"@msnews/isomorphic-util\";\r\n\r\n/** Default values for border radius */\r\nconst borderRadiusCopyLink = 2;\r\nconst borderRadiusDialog = 4;\r\n\r\n/**\r\n * Default color values for the share dialog\r\n */\r\nconst ShareDialogColors = {\r\n dividerLine: \"rgba(0,0,0, 0.05)\",\r\n inputText: \"rgba(0, 1, 0, 0.6)\",\r\n inputBorder: \"rgba(0, 0, 0, 0.2)\",\r\n copyLinkButtonBackground: \"#0078D4\",\r\n copyLinkButtonBackgroundActive: \"#1B64B0\",\r\n copyLinkButtonText: \"#FFF\",\r\n dialogOverlayBackground: \"rgba(0, 0, 0, 0.4)\"\r\n};\r\n\r\n/**\r\n * The JSS stylesheet for the base dialog\r\n * @type {ComponentStyles}\r\n * @param {DesignSystem} config - The design system configuration interface\r\n */\r\nexport const baseDialogStyles: ComponentStyles = (config: DesignSystem) => {\r\n const backgroundColor: string = get(config, \"backgroundColor\", DesignSystemDefaults.backgroundColor);\r\n\r\n return {\r\n dialog: {\r\n display: \"none\",\r\n '&[aria-hidden=\"false\"]': {\r\n display: \"block\"\r\n }\r\n },\r\n dialog_modalOverlay: {\r\n position: \"fixed\",\r\n background: ShareDialogColors.dialogOverlayBackground,\r\n top: \"0\",\r\n left: \"0\",\r\n right: \"0\",\r\n bottom: \"0\",\r\n \"z-index\": `${ZIndex.Above}`\r\n },\r\n dialog_contentRegion: {\r\n position: \"fixed\",\r\n left: \"50%\",\r\n top: \"50%\",\r\n transform: \"translate(-50%, -50%)\",\r\n \"border-radius\": toPx(borderRadiusDialog),\r\n \"box-shadow\": \"none\",\r\n \"z-index\": `${ZIndex.Above + 1}`,\r\n ...applyAcrylicMaterial(backgroundColor, 0.7, 0.7, true)\r\n }\r\n };\r\n};\r\n\r\n /**\r\n * Gets the override style for base dialog based on ZIndex\r\n * @private\r\n * @method\r\n * @return {>} the result style to be passed to base dialog\r\n */\r\nexport const setStyleByZIndex = memoize((overrides: ComponentStyleSheet = {}, zIndex: number = null) => {\r\n return zIndex == null ? overrides : {\r\n ...overrides,\r\n dialog_modalOverlay: {\r\n ...overrides.dialog_modalOverlay,\r\n \"z-index\": zIndex.toString()\r\n },\r\n dialog_contentRegion: {\r\n ...overrides.dialog_contentRegion,\r\n \"z-index\": (zIndex + 1).toString()\r\n }\r\n };\r\n});\r\n\r\n/**\r\n * The JSS stylesheet for the share dialog\r\n * @type {ComponentStyles}\r\n * @param {DesignSystem} config - The design system configuration interface\r\n */\r\nexport const ShareDialogStyles: ComponentStyles = (config: DesignSystem) => {\r\n const iconWidth = 40;\r\n const headerLineHeight = 20;\r\n const backdropFilterStyles: CSSRules = {\r\n background: \"none\"\r\n };\r\n const fallbackStyles: CSSRules = {\r\n background: get(config, \"backgroundColor\", DesignSystemDefaults.backgroundColor)\r\n };\r\n const backdropFilterSupport: boolean = canUseDOM() && (\"backdrop-filter\" in document.documentElement.style || \"-webkit-backdrop-filter\" in document.documentElement.style);\r\n const backgroundStyle: CSSRules = backdropFilterSupport ? backdropFilterStyles : fallbackStyles;\r\n return {\r\n closeButton: {\r\n background: \"transparent\",\r\n border: \"none\",\r\n height: toPx(headerLineHeight),\r\n position: \"absolute\",\r\n [applyLocalizedProperty(\"right\", \"left\", config.direction)]: \"4px\",\r\n \"&:hover\": {\r\n cursor: \"pointer\"\r\n }\r\n },\r\n closeIcon: {\r\n fill: neutralForegroundRest\r\n },\r\n copyLinkButton: {},\r\n copyLinkInput: {},\r\n dialogContainer: {\r\n ...backgroundStyle,\r\n \"border-radius\": toPx(borderRadiusDialog),\r\n padding: \"0 12px\",\r\n width: \"322px\",\r\n \"box-sizing\": \"content-box\",\r\n \"& $inputContainer\": {\r\n \"& $copyLinkInput\": {\r\n [applyLocalizedProperty(\"border-top-left-radius\", \"border-top-right-radius\", config.direction)]: toPx(borderRadiusCopyLink),\r\n [applyLocalizedProperty(\"border-bottom-left-radius\", \"border-bottom-right-radius\", config.direction)]: toPx(borderRadiusCopyLink)\r\n }\r\n }\r\n },\r\n header: {\r\n \"border-bottom\": `${config.outlineWidth}px solid ${ShareDialogColors.dividerLine}`,\r\n display: \"flex\",\r\n \"line-height\": toPx(headerLineHeight),\r\n padding: \"16px 0 12px 0\",\r\n \"text-align\": \"center\"\r\n },\r\n headerText: {\r\n ...applyTypeRampConfig(\"t7\"),\r\n \"font-weight\": `${fontWeight.semibold}`,\r\n margin: \"0\",\r\n width: \"100%\"\r\n },\r\n iconListContainer: {\r\n display: \"inline-block\",\r\n \"list-style\": \"none\",\r\n \"text-align\": \"center\",\r\n margin: \"36px 11px 0 11px\",\r\n padding: \"0\"\r\n },\r\n iconListItem: {\r\n float: applyLocalizedProperty(\"left\", \"right\", config.direction),\r\n width: toPx(iconWidth),\r\n [applyLocalizedProperty(\"margin-right\", \"margin-left\", config.direction)]: \"40px\",\r\n \"&:nth-child(4)\": {\r\n [applyLocalizedProperty(\"margin-right\", \"margin-left\", config.direction)]: 0\r\n },\r\n \"&:nth-child(n+5)\": {\r\n \"margin-top\": \"24px\"\r\n },\r\n \"&:nth-child(4n+1)\": {\r\n clear: \"both\"\r\n }\r\n },\r\n inputContainer: {\r\n \"box-sizing\": \"content-box\",\r\n \"padding-top\": \"24px\",\r\n \"padding-bottom\": \"32px\",\r\n \"text-align\": \"center\",\r\n \"& $copyLinkInput\": {\r\n border: `1px solid ${ShareDialogColors.inputBorder}`,\r\n \"box-sizing\": \"content-box\",\r\n color: ShareDialogColors.inputText,\r\n ...applyTypeRampConfig(\"t8\"),\r\n padding: \"1px 0 1px 5px\",\r\n height: \"28px\",\r\n width: \"191px\"\r\n },\r\n \"& $copyLinkButton\": {\r\n background: ShareDialogColors.copyLinkButtonBackground,\r\n [applyLocalizedProperty(\"border-top-right-radius\", \"border-top-left-radius\", config.direction)]: toPx(borderRadiusCopyLink),\r\n [applyLocalizedProperty(\"border-bottom-right-radius\", \"border-bottom-left-radius\", config.direction)]: toPx(borderRadiusCopyLink),\r\n border: \"none\",\r\n color: ShareDialogColors.copyLinkButtonText,\r\n ...applyTypeRampConfig(\"t8\"),\r\n height: \"32px\",\r\n width: \"89px\",\r\n \"&:hover\": {\r\n cursor: \"pointer\"\r\n },\r\n \"&:active\": {\r\n background: ShareDialogColors.copyLinkButtonBackgroundActive\r\n }\r\n }\r\n }\r\n };\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\n/** String resource to be used in the Card Action components */\r\nexport const StringResource = {\r\n dialogStrings: {\r\n dialogButtonClose: \"close dialog\",\r\n dialogTitle: \"Share\",\r\n copyButton: \"Copy\",\r\n copiedButton: \"Link Copied\",\r\n copyButtonAriaLabel: \"copy link to clipboard\",\r\n copiedButtonAriaLabel: \"link copied to clipboard\"\r\n }\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n DialogProps,\r\n Dialog as MSFTBaseDialog\r\n} from \"@microsoft/fast-components-react-base\";\r\nimport { GlyphInline, Icon } from \"@msnews/icon\" ;\r\nimport {\r\n Heading,\r\n HeadingSize,\r\n HeadingTag\r\n} from \"@microsoft/fast-components-react-msft\";\r\nimport { ShareDialogHandledProps, ShareDialogProps, ShareDialogStrings } from \"./ShareDialog.props\";\r\nimport {\r\n SocialMedia,\r\n SocialMediaConfig,\r\n SocialMediaDefaultConfig\r\n} from \"@msnews/views-helpers\";\r\nimport { Telemetry, TelemetryTags } from \"@msnews/experiences-base\";\r\nimport { baseDialogStyles, setStyleByZIndex } from \"./ShareDialog.styles\";\r\n\r\nimport Foundation from \"@microsoft/fast-components-foundation-react\";\r\nimport { HandledPropsKeys } from \"@msnews/core\";\r\nimport React from \"react\";\r\nimport { SocialMediaIcon } from \"@msnews/social-media-icon\";\r\nimport { StringResource } from \"./StringResource\";\r\nimport { logger } from \"@msnews/diagnostics\";\r\nimport manageJss from \"@microsoft/fast-jss-manager-react\";\r\n\r\n/** Base MSFT dialog with overriden style */\r\nconst Dialog = manageJss(baseDialogStyles)(MSFTBaseDialog);\r\n\r\n/** Duration the button should present the \"link copied\" text after a user click */\r\nconst linkCopiedDisplayDuration = 1600;\r\n\r\n/**\r\n * Share dialog state interface\r\n * @export\r\n * @interface ShareDialogState\r\n */\r\nexport interface ShareDialogState {\r\n isLinkCopied: boolean\r\n}\r\n/**\r\n * ShareDialog Component\r\n * @class - ShareDialog\r\n * @classdesc - The ShareDialog component. Renders the dialog that provides social media sharing options\r\n * @default\r\n */\r\nexport class ShareDialog extends Foundation {\r\n /**\r\n * Component HandledProps enumeration. Anything not enumerated here will be included in the experience root HTML tag via unhandledProps()\r\n */\r\n protected handledProps: HandledPropsKeys = {\r\n baseDialogProps: undefined,\r\n closeButtonTelemetryTags: undefined,\r\n contentTitle: undefined,\r\n contentUrl: undefined,\r\n copyButtonAttributes: undefined,\r\n copyButtonTelemetryProps: undefined,\r\n copyButtonTelemetryTags: undefined,\r\n copyLinkOcid: undefined,\r\n dialogStrings: undefined,\r\n enabled: undefined,\r\n managedClasses: undefined,\r\n onClose: undefined,\r\n socialMediaConfigOverride: undefined,\r\n socialMediaItems: undefined,\r\n shareIconTelemetryProps: undefined,\r\n shareIconTelemetryTags: undefined,\r\n baseDialogStyleOverride: undefined,\r\n zIndex: undefined\r\n };\r\n\r\n /**\r\n * Stores the strings to be used in the dialog. Merged default strings with passed from props\r\n * @type {ShareDialogStrings}\r\n */\r\n private dialogStrings: ShareDialogStrings;\r\n\r\n /**\r\n * Social media items config that stores merged values from default and props\r\n * @type {SocialMediaConfig}\r\n */\r\n private socialMediaItemsConfig: SocialMediaConfig;\r\n\r\n /**\r\n * Ref to input field with shared url\r\n * @type {React.RefObject}\r\n */\r\n private readonly inputRef: React.RefObject = React.createRef();\r\n\r\n /**\r\n * Constructs a ShareDialog component\r\n * @constructor\r\n * @param { ShareDialogProps } props props contract\r\n */\r\n constructor(props: ShareDialogProps) {\r\n super(props);\r\n this.state = {\r\n isLinkCopied: false\r\n };\r\n\r\n // Merges some values from props with default values\r\n this.dialogStrings = { ...StringResource.dialogStrings, ...props.dialogStrings };\r\n\r\n this.setSocialMediaItemsConfig();\r\n }\r\n\r\n /**\r\n * Component renderer\r\n * @public\r\n * @method\r\n * @returns {JSX.Element} the ShareDialog component\r\n */\r\n public render(): JSX.Element {\r\n const { managedClasses, enabled, contentUrl, baseDialogProps, onClose, children, closeButtonTelemetryTags, baseDialogStyleOverride, zIndex } = this.props;\r\n if (!enabled || !contentUrl) {\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n
\r\n
\r\n \r\n {this.dialogStrings.dialogTitle}\r\n \r\n \r\n \r\n \r\n
\r\n {children}\r\n {this.renderSocialIconsList()}\r\n {this.renderCopyLink()}\r\n
\r\n \r\n );\r\n }\r\n\r\n /**\r\n * Renders the copy link input and button part of the share dialog\r\n * @private\r\n * @method\r\n * @returns {JSX.Element} the content part of the ShareDialog component\r\n */\r\n private renderCopyLink(): JSX.Element {\r\n const { managedClasses, copyLinkOcid, contentUrl, copyButtonAttributes, copyButtonTelemetryProps, copyButtonTelemetryTags } = this.props;\r\n\r\n const url = copyLinkOcid ? `${contentUrl}?ocid=${copyLinkOcid}` : contentUrl;\r\n const buttonText = this.state.isLinkCopied ? this.dialogStrings.copiedButton : this.dialogStrings.copyButton;\r\n const ariaLabel = this.state.isLinkCopied ? this.dialogStrings.copiedButtonAriaLabel : this.dialogStrings.copyButtonAriaLabel;\r\n\r\n const copyTelemetryTag = copyButtonTelemetryTags || Telemetry.render(copyButtonTelemetryProps);\r\n\r\n return (\r\n
\r\n \r\n \r\n {buttonText}\r\n \r\n
\r\n );\r\n }\r\n\r\n /**\r\n * Copy share url to clipboard and set timer to update the copy link button text\r\n * @private\r\n * @method\r\n */\r\n private onCopyLinkToClipboard = () => {\r\n if (!this.state.isLinkCopied) {\r\n this.setState({ isLinkCopied: true });\r\n this.inputRef.current.select();\r\n document.execCommand(\"copy\");\r\n setTimeout(() => {\r\n /* istanbul ignore next */\r\n this.setState({ isLinkCopied: false });\r\n },\r\n linkCopiedDisplayDuration\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Renders the social items list part of the share dialog\r\n * @private\r\n * @method\r\n * @returns {JSX.Element} the social media list element of the ShareDialog component\r\n */\r\n private renderSocialIconsList(): JSX.Element {\r\n const { managedClasses, socialMediaItems } = this.props;\r\n if (!socialMediaItems || !socialMediaItems.length) {\r\n return null;\r\n }\r\n\r\n const socialMediaIcons = socialMediaItems.map((item) => {\r\n return this.renderSocialIcon(item);\r\n });\r\n\r\n return (\r\n
    \r\n {socialMediaIcons}\r\n
\r\n );\r\n }\r\n\r\n /**\r\n * Renders each individual social media icon of the social media list\r\n * @private\r\n * @method\r\n * @param { string } socialMediaItem The social media item as string\r\n * @returns {JSX.Element} the icon part of the social media list\r\n */\r\n private renderSocialIcon(socialMediaItem: string): JSX.Element {\r\n const { managedClasses, shareIconTelemetryProps, shareIconTelemetryTags, contentTitle, contentUrl } = this.props;\r\n const media: SocialMedia = SocialMedia[Object.keys(SocialMedia).find(key => SocialMedia[key] === socialMediaItem.toLowerCase())];\r\n if (!media) {\r\n logger.logError(`ShareDialog: renderSocialIcon: Invalid param: socialMediaItem = ${socialMediaItem}`);\r\n return null;\r\n }\r\n const mediaKey = media.toString();\r\n\r\n const iconTelemetryTags: TelemetryTags = (shareIconTelemetryTags && shareIconTelemetryTags[mediaKey]) ||\r\n (shareIconTelemetryProps && Telemetry.render(shareIconTelemetryProps[mediaKey]));\r\n\r\n return (\r\n
  • \r\n \r\n
  • \r\n );\r\n }\r\n\r\n /**\r\n * Sets configuration specs for social media items based on default and override props values\r\n * @method\r\n */\r\n private setSocialMediaItemsConfig(): void {\r\n this.socialMediaItemsConfig = { ...SocialMediaDefaultConfig };\r\n\r\n // merge default config with override props\r\n if (this.props.socialMediaConfigOverride) {\r\n Object.keys(this.props.socialMediaConfigOverride).forEach((key) => {\r\n const keyLower = key.toLowerCase();\r\n this.socialMediaItemsConfig[keyLower] = { ...this.socialMediaItemsConfig[keyLower], ...this.props.socialMediaConfigOverride[key] };\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Gets the final props to apply to the dialog component\r\n * @private\r\n * @method\r\n * @param {DialogProps} props - the default dialog props\r\n * @returns {DialogProps} the resulting props to be passed to base dialog\r\n */\r\n private coerceDialogProps(props: DialogProps): DialogProps {\r\n return {\r\n visible: this.props.enabled,\r\n modal: true,\r\n contentHeight: \"auto\",\r\n contentWidth: \"346px\",\r\n ...props\r\n };\r\n }\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n ShareDialogHandledProps as BaseShareDialogHandledProps,\r\n ShareDialogProps as BaseShareDialogProps,\r\n ShareDialogManagedClasses,\r\n ShareDialogStrings,\r\n ShareDialogUnhandledProps\r\n} from \"./ShareDialog.props\";\r\nimport manageJss, { ManagedJSSProps } from \"@microsoft/fast-jss-manager-react\";\r\n\r\nimport { ShareDialog as BaseShareDialog } from \"./ShareDialog\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { ShareDialogClassNameContract } from \"./ShareDialog.classnames\";\r\nimport { ShareDialogStyles } from \"./ShareDialog.styles\";\r\nimport { Subtract } from \"utility-types\";\r\n\r\n/* The type returned by manageJss type is very complicated so we'll let the\r\n* compiler infer the type instead of re-declaring just for the package export\r\n*/\r\nconst ShareDialog = manageJss(ShareDialogStyles)(BaseShareDialog);\r\ntype ShareDialog = InstanceType;\r\n\r\n// Create a valid JSS managed interface that doesn't require managed classes which are provided by the manageJSS HOC\r\ninterface ShareDialogHandledProps\r\n extends Subtract {}\r\n\r\n// Create type for manageJSS HOC styled instance we are exporting\r\ntype ShareDialogProps = ManagedJSSProps<\r\n BaseShareDialogProps,\r\n ShareDialogClassNameContract,\r\n DesignSystem\r\n>;\r\n\r\n// Export everything a user might need from this index file\r\nexport {\r\n ShareDialog,\r\n ShareDialogProps,\r\n ShareDialogHandledProps,\r\n ShareDialogUnhandledProps,\r\n ShareDialogManagedClasses,\r\n ShareDialogClassNameContract,\r\n ShareDialogStrings\r\n};\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ArticleCardHandledProps, ArticleCardProps, ArticleCardUnhandledProps } from \"./ArticleCard.props\";\r\nimport { HandledPropsKeys, ShallowCompare } from \"@msnews/core\";\r\nimport { Heading, Image, Typography } from \"@microsoft/fast-components-react-msft\";\r\n\r\nimport Foundation from \"@microsoft/fast-components-foundation-react\";\r\nimport React from \"react\";\r\n\r\n/**\r\n * Article card state interface\r\n */\r\nexport interface ArticleCardState {}\r\n\r\n/**\r\n * Article card component\r\n * @class - Article card\r\n * @classdesc - Article card component base; provides semantic structure of a basic article card.\r\n * @export\r\n * @default\r\n */\r\nclass ArticleCard extends Foundation {\r\n /**\r\n * Article card handled props contract\r\n * @protected\r\n * @type { HandledPropsKeys}\r\n */\r\n protected handledProps: HandledPropsKeys = {\r\n anchorRef: undefined,\r\n headlineTitle: undefined,\r\n href: undefined,\r\n image: undefined,\r\n managedClasses: undefined,\r\n provider: undefined\r\n };\r\n\r\n /**\r\n * Construct a new article card\r\n * @constructor\r\n * @param { ArticleCardHandledProps } props the props contract for ArticleCard\r\n */\r\n constructor(props: ArticleCardHandledProps) {\r\n super(props);\r\n }\r\n\r\n /**\r\n * Performs a shallow comparison on the props\r\n * @param nextProps Incoming props\r\n * @param nextState Incoming state. Ignored as component is stateless\r\n */\r\n public shouldComponentUpdate(nextProps: ArticleCardProps): boolean {\r\n return !ShallowCompare(this.props, nextProps);\r\n }\r\n\r\n /**\r\n * Renders the component\r\n * @method\r\n * @returns {JSX.Element} the ArticleCard JSX element\r\n */\r\n public render(): JSX.Element {\r\n return (\r\n \r\n {this.renderContent()}\r\n {this.props.children}\r\n \r\n );\r\n }\r\n\r\n /**\r\n * Renders the content component of the article\r\n * @method\r\n * @returns {JSX.Element} the content of an article\r\n */\r\n private renderContent(): JSX.Element {\r\n let content: JSX.Element;\r\n const { href, managedClasses } = this.props;\r\n\r\n if (href) {\r\n content = (\r\n \r\n {this.renderImage()}\r\n
    \r\n {this.renderTitle()}\r\n {this.renderProvider()}\r\n
    \r\n
    \r\n );\r\n } else {\r\n content = (\r\n
    \r\n {this.renderImage()}\r\n
    \r\n {this.renderTitle()}\r\n {this.renderProvider()}\r\n
    \r\n
    \r\n );\r\n }\r\n\r\n return content;\r\n }\r\n\r\n /**\r\n * Renders the card image component of the article\r\n * @method\r\n * @returns {JSX.Element} the image component of an article\r\n */\r\n private renderImage(): JSX.Element {\r\n if (!this.props.image) {\r\n return;\r\n }\r\n\r\n const { articleCard_imageWrapper, articleCard_image, articleCard_imageOverlay } = this.props.managedClasses;\r\n\r\n return (\r\n
    \r\n \r\n
    \r\n
    \r\n );\r\n }\r\n\r\n /**\r\n * Renders the headline title component of the article\r\n * @method\r\n * @returns {JSX.Element} the headline title component of an article\r\n */\r\n private renderTitle(): JSX.Element {\r\n const { articleCard_headline, articleCard_headlineText, articleCard_headlineMask } = this.props.managedClasses;\r\n\r\n return (\r\n
    \r\n \r\n
    \r\n
    \r\n );\r\n }\r\n\r\n /**\r\n * Renders the article provider component of an article\r\n * @method\r\n * @returns {JSX.Element} the article provider component if it exists\r\n */\r\n private renderProvider(): JSX.Element {\r\n if (!this.props.provider) {\r\n return;\r\n }\r\n\r\n let providerImage: JSX.Element;\r\n if (this.props.provider.image && this.props.provider.image.src) {\r\n providerImage = (\r\n \r\n );\r\n }\r\n\r\n return (\r\n
    \r\n {providerImage}\r\n \r\n
    \r\n );\r\n }\r\n}\r\n\r\nexport default ArticleCard;\r\nexport * from \"./ArticleCard.props\";","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { SocialMedia, SocialMediaDefaultConfig } from \"./SocialMediaConfig\";\r\nimport { getLocationHref, getLocationOrigin } from \"@msnews/isomorphic-util\";\r\nimport { indexOf, uniqueId } from \"lodash-es\";\r\n\r\nimport { String } from \"typescript-string-operations\";\r\nimport { format } from \"@microsoft/fast-web-utilities\";\r\nimport { getAppEnvironment } from \"@msnews/core\";\r\nimport { logger } from \"@msnews/diagnostics\";\r\n\r\n/**\r\n * Document type being shared\r\n */\r\nexport enum SharedDocumentType {\r\n CMS = \"0\",\r\n SD = \"5\"\r\n}\r\n\r\n/**\r\n * Sharing details interface to build sharing items\r\n * @interface\r\n */\r\nexport interface SharingInfo {\r\n /**\r\n * CMS document id\r\n * @type {string}\r\n */\r\n documentId: string;\r\n\r\n /**\r\n * Document type\r\n * @type {SharedDocumentType}\r\n */\r\n documentType: SharedDocumentType;\r\n\r\n /**\r\n * Sharing url for the content\r\n * @type {string}\r\n */\r\n sharingUrl?: string;\r\n}\r\n\r\n/**\r\n * Helper for building sharing details\r\n * @class\r\n */\r\nexport class SharingHelper {\r\n /**\r\n * Base production url used in the sharing link\r\n */\r\n private static readonly SharingBaseUrlDefault: string = \"http://a.msn.com/\";\r\n\r\n /**\r\n * Path format used to build the sharing url\r\n */\r\n private static readonly shortUrlPathFormat: string = \"{0}{1}/{2}/{3}\";\r\n\r\n /**\r\n * List the available options that should be mapped to prod url\r\n */\r\n private static readonly SharingProductionHosts: string = \"bing.com|www.bing.com|preview.msn.com|www.msn.com\";\r\n\r\n /**\r\n * String used to map the AppId number to single char identifier required in the sharing url\r\n */\r\n private static readonly Base36AppIdString: string = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\r\n\r\n /**\r\n * Path format used to append querystring to the sharing url\r\n */\r\n private static readonly appendQueryStringFormat: string = \"{0}?ocid={1}\";\r\n\r\n /**\r\n * List of available vertical keys to be mapped.\r\n * The order matter here as the AppId to be used is based on the array index of the key\r\n */\r\n private static readonly AppKeys: string[] = [\"finance\",\r\n \"news\",\r\n \"sports\",\r\n \"travel\",\r\n \"weather\",\r\n \"health\",\r\n \"foodanddrink\",\r\n \"entertainment\",\r\n \"autos\",\r\n \"video\",\r\n \"tv\",\r\n \"music\",\r\n \"movies\",\r\n \"games\",\r\n \"lifestyle\",\r\n \"kids\",\r\n \"sample\",\r\n \"asia\",\r\n \"africa\",\r\n \"australasia\",\r\n \"europe\",\r\n \"latinamerica\",\r\n \"middleeast\",\r\n \"northamerica\"];\r\n\r\n /**\r\n * Builds the short url that links to the article to be shared\r\n * @param sharingInfo The sharing data based on SharingInfo interface\r\n * @param locale The locale\r\n * @returns String with the short url to be shared\r\n */\r\n public static shortUrlBuilder(sharingInfo: SharingInfo, locale: string): string {\r\n const appId = this.getAppId();\r\n if (!appId) {\r\n return null;\r\n }\r\n\r\n const baseUrl = this.getSharingUrlBase(sharingInfo.sharingUrl);\r\n\r\n return baseUrl + format(this.shortUrlPathFormat, sharingInfo.documentType, appId, locale, sharingInfo.documentId);\r\n }\r\n\r\n /**\r\n * Gets the base36 AppId that is mapped from the vertical key identifier\r\n * @returns The mapped AppId\r\n */\r\n public static getAppId(): string {\r\n const { HostPage } = getAppEnvironment();\r\n const verticalKey: string = ((HostPage && HostPage.verticalKey) || \"news\").toLowerCase();\r\n let appId = indexOf(this.AppKeys, verticalKey);\r\n if (appId === -1 || appId >= this.Base36AppIdString.length) {\r\n appId = 1;\r\n }\r\n const base36Id = this.Base36AppIdString.substr(appId, 1);\r\n return base36Id;\r\n }\r\n\r\n /**\r\n * Gets the base url to be used in the shared link\r\n * @param articleUrl The full article url\r\n * @returns The base url to be used in the shared link\r\n */\r\n public static getSharingUrlBase(articleUrl: string): string {\r\n const url = new URL(articleUrl, getLocationOrigin());\r\n\r\n const host = url.host;\r\n const currentBaseUrl = url.origin + \"/\";\r\n\r\n const splitUrls = this.SharingProductionHosts.split(\"|\");\r\n\r\n const baseUrl = splitUrls.indexOf(host) > -1 ? this.SharingBaseUrlDefault : currentBaseUrl;\r\n\r\n return baseUrl;\r\n }\r\n\r\n /**\r\n * Strips off query string params\r\n * @param url Input url\r\n * @returns The plain url\r\n */\r\n public static getUrlWithoutQueryParams(url: string): string {\r\n if (url && url.length > 0) {\r\n return url.split(\"?\")[0];\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Retrieves the URL for sharing with Social Media.\r\n * @param medias social media to be included\r\n * @param contentUrl The url of the content to be shared\r\n * @param contentTitle The title of the content\r\n * @param ocid The ocid to be included in the shared link\r\n * @returns The share url\r\n */\r\n public static getSocialMediaShareUrl(media: string, contentUrl: string, contentTitle: string, ocid?: string, overrideShareUrl?: string): string {\r\n if (!media || !contentUrl || !contentTitle) {\r\n logger.logError(`SharingHelper: getSocialMediaShareUrl: Parameter missing: media=${media}, contentUrl=${contentUrl}, contentTitle=${contentTitle}`);\r\n return;\r\n }\r\n\r\n let socialMediaItemConfig = SocialMediaDefaultConfig[media];\r\n if (!socialMediaItemConfig ) {\r\n logger.logError(`SharingHelper: getSocialMediaShareUrl: Cannot find media type: ${socialMediaItemConfig}`);\r\n return \"\";\r\n }\r\n\r\n let shareUrl = overrideShareUrl || socialMediaItemConfig.url;\r\n if (media === SocialMedia.Skype ) {\r\n shareUrl = shareUrl.replace(\"{flowid}\", uniqueId());\r\n }\r\n\r\n if (ocid) {\r\n contentUrl = format(this.appendQueryStringFormat, contentUrl, ocid);\r\n }\r\n\r\n shareUrl = String.Format(shareUrl, {\r\n url: encodeURIComponent(contentUrl),\r\n title: encodeURIComponent(contentTitle),\r\n refererUrl: getLocationHref()\r\n });\r\n\r\n return shareUrl;\r\n }\r\n\r\n /**\r\n * Opens the social media sharing page in a new window\r\n * @param event Mouse event\r\n * @param shareUrl The complete url to be shared\r\n * @param options The features optional parameter in window.open\r\n */\r\n public static openNewWindow = (event: React.MouseEvent, shareUrl: string, options?: any): void => {\r\n const defaultOptions = { \"toolbar\": 0, \"status\": 0, \"resizable\": 1, \"scrollbars\": 1 };\r\n const finalOptions = Object.entries({ ...defaultOptions, ...options })\r\n .map(entry => entry.join(\"=\"))\r\n .join(\",\");\r\n\r\n window.open(shareUrl, null, finalOptions);\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\n/**\r\n * Default name for the content action toolbar experience\r\n */\r\nexport const experienceDefaultName = \"ContentActionsToolbar\";\r\n\r\n/**\r\n * Windows sizes to trigger breakpoint tracker\r\n */\r\nexport const BreakpointIndexToPx = [0, 1152, 1263];\r\n\r\n/**\r\n * The breakpoint indexes to be maped by breakpoint tracker\r\n */\r\nexport enum ToolbarBreakpoints {\r\n Breakpoint3_1 = 0,\r\n Breakpoint3_2 = 1,\r\n Breakpoint3_3 = 2\r\n}\r\n\r\n/**\r\n * Constant names for telemetry data\r\n */\r\nexport enum TelemetryConstants {\r\n socialToolbarTelemetryName = \"socialtoolbar\",\r\n closeDialogTelemetryName = \"Close\",\r\n copyLinkTelemetryName = \"CopyLink\",\r\n shareArticleTelemetryName = \"ShareArticle\",\r\n shareDialogTelemetryName = \"ShareDialog\"\r\n}\r\n\r\n/**\r\n * Spa placeholders Ids\r\n */\r\nexport enum PlaceHolderId {\r\n vertical = \"content-actions-toolbar-vert\",\r\n horizontal = \"content-actions-toolbar-horiz\"\r\n}\r\n\r\n/**\r\n * Action keys for like/dislike\r\n */\r\nexport enum LikeDislikeActionKey {\r\n like = \"like\",\r\n dislike = \"dislike\",\r\n undoliked = \"undoliked\",\r\n undodisliked = \"undodisliked\"\r\n}\r\n\r\n/**\r\n * action keys available in content action\r\n */\r\nexport enum SelectPropKey {\r\n onLike = \"onLike\",\r\n onDislike = \"onDislike\",\r\n onOpenOptions = \"onOpenOptions\",\r\n onShareDialogOpen = \"onShareDialogOpen\"\r\n}\r\n\r\n/**\r\n * Content Status\r\n */\r\nexport enum Status {\r\n None = \"none\",\r\n Like = \"like\",\r\n DisLike = \"dislike\"\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { SocialMedia, SocialMediaTarget } from \"@msnews/views-helpers\";\r\n\r\nimport { CardContextMenuItem } from \"@msnews/card-context-menu\";\r\nimport { DialogArticleCardProps } from \"../dialog-article-card\";\r\nimport { GlyphType } from \"@msnews/icon\";\r\nimport { ManagedClasses } from \"@microsoft/fast-components-class-name-contracts-msft\";\r\nimport { ShareDialogProps } from \"@msnews/share-dialog\";\r\nimport { SharingToolbarClassNames } from \"./\";\r\nimport { Status } from \"../../ContentActionsToolbar.constants\";\r\nimport { TelemetryTags } from \"@msnews/experiences-base\";\r\nimport { ToolbarPosition } from \"../..\";\r\n\r\n/**\r\n * Enumeration of available button type options\r\n * @type {enum}\r\n */\r\nexport enum ButtonType {\r\n SocialMedia = \"SocialMedia\",\r\n ShareDialog = \"ShareDialog\",\r\n LikeDislike = \"LikeDislike\",\r\n MoreOptions = \"MoreOptions\"\r\n}\r\n\r\n/**\r\n * Coordinate position type\r\n */\r\nexport type CoordinatePos = {\r\n /**\r\n * A horizontal coordinate position\r\n * @type {number}\r\n */\r\n x: number;\r\n\r\n /**\r\n * A vertical coordinate position\r\n * @type {number}\r\n */\r\n y: number;\r\n};\r\n\r\n/**\r\n * The social media type button\r\n */\r\nexport type SocialMediaType = {\r\n /**\r\n * Optional HTML anchor attributes\r\n * @type {React.HTMLAttributes}\r\n */\r\n attributes?: React.HTMLAttributes;\r\n\r\n /**\r\n * The social media enum type\r\n * @type {SocialMedia}\r\n */\r\n mediaType: SocialMedia;\r\n\r\n /**\r\n * The shared content url\r\n * @type {string}\r\n */\r\n contentUrl: string;\r\n\r\n /**\r\n * The shared content title\r\n * @type {string}\r\n */\r\n contentTitle: string;\r\n\r\n /**\r\n * The icon to be used instead of default one\r\n * @type {GlyphType}\r\n */\r\n icon?: GlyphType;\r\n\r\n /**\r\n * The ocid value to be used\r\n * @type {string}\r\n */\r\n ocid?: string;\r\n\r\n /**\r\n * The social media anchor target attribute option to be used\r\n * @type {SocialMediaTarget}\r\n */\r\n target?: SocialMediaTarget;\r\n\r\n /**\r\n * The telemetry callback to triggered when new window is used as the anchor target\r\n * @type {(event: any) => void}\r\n */\r\n newWindowTelemetryCall?: (event: any) => void;\r\n};\r\n\r\n/**\r\n * The share dialog type button\r\n */\r\nexport type ShareDialogType = {\r\n /**\r\n * Optional HTML button attributes\r\n * @type {React.HTMLAttributes}\r\n */\r\n attributes?: React.HTMLAttributes;\r\n\r\n /**\r\n * The share dialog component props\r\n * @type {ShareDialogProps}\r\n */\r\n shareDialogProps: ShareDialogProps;\r\n\r\n /**\r\n * The dialog article card component props\r\n * @type {DialogArticleCardProps}\r\n */\r\n dialogArticleCardProps: DialogArticleCardProps;\r\n\r\n /**\r\n * The telemetry tags\r\n * @type {TelemetryTags}\r\n */\r\n articleTelemetryTags?: TelemetryTags;\r\n\r\n /**\r\n * Callback to be triggered at user click\r\n * @type {(event: any) => void}\r\n */\r\n onSelect?: (event: any) => void;\r\n};\r\n\r\n/**\r\n * The like/dislike type button\r\n */\r\nexport type LikeDislikeType = {\r\n /**\r\n * Optional HTML button attributes\r\n * @type {React.HTMLAttributes}\r\n */\r\n attributes?: React.HTMLAttributes;\r\n\r\n /**\r\n * Current status (like/dislike/none) of the content\r\n * @type {Status}\r\n */\r\n status: Status;\r\n\r\n /**\r\n * Callback to be triggered at user click\r\n * @type {(event: any) => void}\r\n */\r\n onSelect?: (event: any) => void;\r\n};\r\n\r\n/**\r\n * The more options type button\r\n */\r\nexport type MoreOptionsType = {\r\n /**\r\n * Optional HTML div attributes\r\n * @type {React.HTMLAttributes}\r\n */\r\n attributes?: React.HTMLAttributes;\r\n\r\n /**\r\n * Current status (like/dislike/none) of the content\r\n * @type {Status}\r\n */\r\n status: Status;\r\n\r\n /**\r\n * The array of items to be displayed in the menu\r\n * @type {CardContextMenuItem[]}\r\n */\r\n menuItems: CardContextMenuItem[];\r\n\r\n /**\r\n * The offset position of the menu to open in relation to its button\r\n * Default to (0,0)\r\n * @type {CoordinatePos}\r\n */\r\n offsetPos?: CoordinatePos;\r\n\r\n /**\r\n * The override zIndex to be used by the menu\r\n * @type {number}\r\n */\r\n zIndex?: number;\r\n};\r\n\r\n/**\r\n * The button item common type\r\n */\r\nexport type ButtonItemType = {\r\n /**\r\n * The content actions toolbar button type\r\n * @type {ButtonType}\r\n */\r\n buttonType: ButtonType;\r\n\r\n /**\r\n * The content actions toolbar button data type\r\n * @type {ButtonDataType}\r\n */\r\n buttonData?: ButtonDataType;\r\n\r\n /**\r\n * The telemetry tags\r\n * @type {TelemetryTags}\r\n */\r\n telemetryTags?: TelemetryTags;\r\n};\r\n\r\nexport type ButtonDataType = Partial;\r\n\r\n/**\r\n * An interface to represent the SharingToolbar jss managed classes.\r\n *\r\n * @export\r\n * @interface SharingToolbarManagedClasses\r\n */\r\nexport interface SharingToolbarManagedClasses extends ManagedClasses { }\r\n\r\n/**\r\n * An interface to represent the SharingToolbar handled props.\r\n *\r\n * @export\r\n * @interface SharingToolbarHandledProps\r\n */\r\nexport interface SharingToolbarHandledProps extends SharingToolbarManagedClasses {\r\n\r\n /**\r\n * The toolbar position (vertical/horizontal)\r\n * @type {ToolbarPosition}\r\n */\r\n position: ToolbarPosition;\r\n\r\n /**\r\n * The sharing buttons configuration array\r\n * @type {ButtonItemType[]}\r\n */\r\n sharingButtons: ButtonItemType[];\r\n}\r\n\r\n/**\r\n * An interface to represent the SharingToolbar unhandled props.\r\n * @export\r\n * @interface SharingToolbarUnHandledProps\r\n */\r\nexport interface SharingToolbarUnHandledProps extends React.HTMLAttributes { }\r\n\r\n/**\r\n * The SharingToolbar props type\r\n */\r\nexport type SharingToolbarProps = SharingToolbarHandledProps & SharingToolbarUnHandledProps;","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ActionMap } from \"@msnews/experiences-redux\";\r\nimport { DocumentData } from \"./ContentActionsToolbar.state\";\r\nimport { Status } from \"./ContentActionsToolbar.constants\";\r\nimport { ToolbarPosition } from \"./ContentActionsToolbar.props\";\r\n\r\ntype InitializeToolbar = (breakpointIndex: number, isRSThreeDevice: boolean, documentId: string, staticPosition: ToolbarPosition) => void;\r\ntype ContentStatuReady = (status: Status) => void;\r\ntype DocumentDataReady = (documentData: DocumentData) => void;\r\ntype LikeContent = () => void;\r\ntype UnlikeContent = () => void;\r\ntype DislikeContent = () => void;\r\ntype UndislikeContent = () => void;\r\ntype ViewportUpdate = (breakpointIndex: number, isRSThreeDevice: boolean) => void;\r\ntype SharingToolbarError = (error: Error) => void;\r\n\r\n/**\r\n * Class containing actions that apply to the ContentActionsToolbar connector\r\n * @class\r\n */\r\nexport class ContentActionsToolbarActions {\r\n public static initializeToolbar: ActionMap = new ActionMap(\"InitializeToolbar\");\r\n public static ContentStatuReady: ActionMap = new ActionMap(\"ContentStatuReady\");\r\n public static documentDataReady: ActionMap = new ActionMap(\"DocumentDataReady\");\r\n public static likeContent: ActionMap = new ActionMap(\"LikeContent\");\r\n public static unlikeContent: ActionMap = new ActionMap(\"UnlikeContent\");\r\n public static dislikeContent: ActionMap = new ActionMap(\"DislikeContent\");\r\n public static undislikeContent: ActionMap = new ActionMap(\"UndislikeContent\");\r\n public static sharingToolbarError: ActionMap = new ActionMap(\"SharingToolbarError\");\r\n public static ViewportUpdate: ActionMap = new ActionMap(\"ViewportUpdate\");\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { CardContextMenuItem } from \"@msnews/card-context-menu\";\r\nimport { CoordinatePos } from \"./SharingToolbar.props\";\r\nimport { Glyph } from \"@msnews/icon\";\r\nimport { LikeDislikeActionKey } from \"../../ContentActionsToolbar.constants\";\r\n\r\n/**\r\n * Default color for the icon container\r\n */\r\nexport const iconContainerDefaultColor = \"#EEE\";\r\n\r\n/**\r\n * Colors for the more options icon\r\n */\r\nexport const moreOptionsIconColors = {\r\n background: iconContainerDefaultColor,\r\n foreground: \"#666\"\r\n};\r\n\r\n/**\r\n * Background colors for the like dislike icon\r\n */\r\nexport const likeDislikeIconBackroundColor = {\r\n none: iconContainerDefaultColor,\r\n like: \"#FF4343\",\r\n dislike: \"#666\"\r\n};\r\n\r\n/**\r\n * Default offset position to display the more options context menu\r\n */\r\nexport const moreOptionsMenuDefaultOffsetPos: CoordinatePos = {\r\n x: 0,\r\n y: -80\r\n};\r\n\r\n/**\r\n * Menu items to render the like option\r\n */\r\nexport const OptionItemLike: CardContextMenuItem = {\r\n key: LikeDislikeActionKey.like,\r\n text: null,\r\n onSelect: null,\r\n icon: Glyph.Like,\r\n telemetryTag: null\r\n};\r\n\r\n/**\r\n * Menu items to render the dislike option\r\n */\r\nexport const OptionItemDislike: CardContextMenuItem = {\r\n key: LikeDislikeActionKey.dislike,\r\n text: null,\r\n onSelect: null,\r\n icon: Glyph.Disliked,\r\n telemetryTag: null\r\n};\r\n\r\n/**\r\n * Menu items to render the undo like option\r\n */\r\nexport const OptionItemUndoLike: CardContextMenuItem = {\r\n key: LikeDislikeActionKey.undoliked,\r\n text: null,\r\n onSelect: null,\r\n icon: Glyph.Like,\r\n telemetryTag: null\r\n};\r\n\r\n/**\r\n * Menu items to render the undo dislike option\r\n */\r\nexport const OptionItemUndoDislike: CardContextMenuItem = {\r\n key: LikeDislikeActionKey.undodisliked,\r\n text: null,\r\n onSelect: null,\r\n icon: Glyph.Dislike,\r\n telemetryTag: null\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ContentActionsToolbarConfig, ContentActionsToolbarProps, ContentActionsToolbarState, Status } from \".\";\r\nimport { InspectorArgs, InspectorResponse } from \"@msnews/core\";\r\nimport { OptionItemDislike, OptionItemLike, OptionItemUndoDislike, OptionItemUndoLike } from \"./components/sharing-toolbar/SharingToolbar.constants\";\r\n\r\nimport { ButtonType } from \"./components/sharing-toolbar/SharingToolbar\";\r\nimport { CardContextMenuItem } from \"@msnews/card-context-menu\";\r\nimport { SocialMediaTarget } from \"@msnews/views-helpers\";\r\nimport { cloneDeep } from \"lodash-es\";\r\n\r\n/**\r\n * Type for ContentActionsToolbar connectorArgs\r\n *\r\n * @export\r\n * @type {ContentActionsToolbarConnectorArgs}\r\n */\r\nexport type ContentActionsToolbarConnectorArgs = {};\r\n\r\nexport type ContentActionsToolbarInspectorArgs = InspectorArgs;\r\n\r\nexport namespace ContentActionsToolbarInspector {\r\n export function inspect(args: ContentActionsToolbarInspectorArgs): InspectorResponse {\r\n const { config, state, config: { localizedStrings } } = args;\r\n\r\n const newProps: ContentActionsToolbarProps = {\r\n staticPosition: state.staticPosition,\r\n position: state.position,\r\n sharingToolbar: {\r\n position: state.position,\r\n sharingButtons: []\r\n },\r\n contentStatus: args.state.status,\r\n sharingError: args.state.sharingError\r\n };\r\n\r\n const sharingShortUrl = state.documentData ? state.documentData.sharingShortUrl : undefined;\r\n const articleTitle = state.documentData ? state.documentData.articleTitle : undefined;\r\n const articleImageUrl = state.documentData ? state.documentData.articleImageUrl : undefined;\r\n const providerName = state.documentData ? state.documentData.providerName : undefined;\r\n const providerLogoUrl = state.documentData ? state.documentData.providerLogoUrl : undefined;\r\n\r\n if (state.status && state.documentData) {\r\n newProps.sharingToolbar.sharingButtons = config.sharingButtons.map(buttonItem => {\r\n let newButtonItem = cloneDeep(buttonItem);\r\n switch (buttonItem.buttonType) {\r\n case ButtonType.SocialMedia:\r\n if (newButtonItem.buttonData) {\r\n newButtonItem.buttonData.contentUrl = sharingShortUrl;\r\n newButtonItem.buttonData.contentTitle = articleTitle;\r\n newButtonItem.buttonData.target = buttonItem.buttonData.target ? SocialMediaTarget[buttonItem.buttonData.target] : undefined;\r\n } else {\r\n newButtonItem = undefined;\r\n }\r\n break;\r\n case ButtonType.ShareDialog:\r\n if (newButtonItem.buttonData && newButtonItem.buttonData.shareDialogProps && newButtonItem.buttonData.shareDialogProps.socialMediaItems) {\r\n const { shareDialogProps } = newButtonItem.buttonData;\r\n shareDialogProps.enabled = true;\r\n shareDialogProps.contentUrl = sharingShortUrl;\r\n shareDialogProps.contentTitle = articleTitle;\r\n shareDialogProps.dialogStrings = {\r\n dialogTitle: localizedStrings.shareDialogTitleText,\r\n copyButton: localizedStrings.shareDialogCopyButtonText,\r\n copyButtonAriaLabel: localizedStrings.shareDialogCopyButtonAriaLabelText,\r\n copiedButton: localizedStrings.shareDialogCopiedButtonText,\r\n copiedButtonAriaLabel: localizedStrings.shareDialogCopiedButtonAriaLabelText\r\n };\r\n\r\n newButtonItem.buttonData.dialogArticleCardProps = {\r\n articleId: state.documentId,\r\n headlineTitle: {\r\n tag: undefined,\r\n children: articleTitle\r\n },\r\n href: sharingShortUrl,\r\n image: {\r\n alt: articleTitle,\r\n src: articleImageUrl\r\n },\r\n provider: {\r\n name: {\r\n title: providerName,\r\n children: providerName\r\n },\r\n image: {\r\n src: providerLogoUrl,\r\n alt: providerName\r\n }\r\n }\r\n };\r\n\r\n newButtonItem.buttonData.attributes = {\r\n \"aria-label\": localizedStrings.shareDialogButtonAriaLabelText,\r\n \"aria-hidden\": false,\r\n \"title\": localizedStrings.shareDialogButtonAriaLabelText\r\n };\r\n } else {\r\n newButtonItem = undefined;\r\n }\r\n break;\r\n case ButtonType.LikeDislike:\r\n newButtonItem.buttonData = {\r\n attributes: {\r\n \"aria-label\": localizedStrings.likeDislikeButtonAriaLabelText,\r\n \"aria-hidden\": false,\r\n \"title\": localizedStrings.likeDislikeButtonAriaLabelText\r\n },\r\n status: state.status\r\n };\r\n break;\r\n case ButtonType.MoreOptions:\r\n let menuItems: CardContextMenuItem[] = [];\r\n if (state.status === Status.Like) {\r\n OptionItemUndoLike.text = localizedStrings.moreOptionsUnlikeText;\r\n OptionItemUndoLike.attr = {\r\n \"aria-label\": localizedStrings.moreOptionsUnlikeAriaLabelText,\r\n \"aria-hidden\": false,\r\n \"title\": localizedStrings.moreOptionsUnlikeAriaLabelText\r\n };\r\n menuItems.push(OptionItemUndoLike);\r\n\r\n OptionItemDislike.text = localizedStrings.moreOptionsDislikeText;\r\n OptionItemDislike.attr = {\r\n \"aria-label\": localizedStrings.moreOptionsDislikeAriaLabelText,\r\n \"aria-hidden\": false,\r\n \"title\": localizedStrings.moreOptionsDislikeAriaLabelText\r\n };\r\n menuItems.push(OptionItemDislike);\r\n } else if (state.status === Status.DisLike) {\r\n OptionItemUndoDislike.text = localizedStrings.moreOptionsUndislikeText;\r\n OptionItemUndoDislike.attr = {\r\n \"aria-label\": localizedStrings.moreOptionsUndislikeAriaLabelText,\r\n \"aria-hidden\": false,\r\n \"title\": localizedStrings.moreOptionsUndislikeAriaLabelText\r\n };\r\n menuItems.push(OptionItemUndoDislike);\r\n\r\n OptionItemLike.text = localizedStrings.moreOptionsLikeText;\r\n OptionItemLike.attr = {\r\n \"aria-label\": localizedStrings.moreOptionsLikeAriaLabelText,\r\n \"aria-hidden\": false,\r\n \"title\": localizedStrings.moreOptionsLikeAriaLabelText\r\n };\r\n menuItems.push(OptionItemLike);\r\n } else {\r\n OptionItemDislike.text = localizedStrings.moreOptionsDislikeText;\r\n OptionItemDislike.attr = {\r\n \"aria-label\": localizedStrings.moreOptionsDislikeAriaLabelText,\r\n \"aria-hidden\": false,\r\n \"title\": localizedStrings.moreOptionsDislikeAriaLabelText\r\n };\r\n menuItems.push(OptionItemDislike);\r\n }\r\n newButtonItem.buttonData = {\r\n attributes: {\r\n \"aria-label\": localizedStrings.moreOptionsButtonAriaLabelText,\r\n \"aria-hidden\": false,\r\n \"title\": localizedStrings.moreOptionsButtonAriaLabelText\r\n },\r\n menuItems: menuItems,\r\n status: state.status,\r\n offsetPos: buttonItem.buttonData ? buttonItem.buttonData.offsetPos : undefined,\r\n zIndex: buttonItem.buttonData ? buttonItem.buttonData.zIndex : undefined\r\n };\r\n break;\r\n default:\r\n break;\r\n }\r\n return newButtonItem;\r\n }).filter(value => value);\r\n }\r\n\r\n return {\r\n props: newProps,\r\n missingChildren: []\r\n };\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n KeyValuePair,\r\n TelemetryBase,\r\n appEnvironment,\r\n headData,\r\n oneServiceQueryStringKeys\r\n} from \"@msnews/core\";\r\nimport { OneServiceUtility, getServiceUrlForSubpath, sendRequest } from \"@msnews/oneservice\";\r\n\r\nimport { ContentActionsToolbarAppErrors } from \"@msnews/diagnostics\";\r\nimport { DocumentData } from \"../ContentActionsToolbar.state\";\r\nimport { Status } from \"../ContentActionsToolbar.constants\";\r\nimport { get } from \"lodash-es\";\r\n\r\n/**\r\n * Class to fetch data for the content actions toolbar experience\r\n * @class ContentActionsToolbarServiceClient\r\n */\r\nexport class ContentActionsToolbarServiceClient {\r\n /**\r\n * The actions service end point\r\n */\r\n private contentActionsServiceEndpoint: string = \"Graph/Actions\";\r\n\r\n /**\r\n * The content preview endpoint\r\n */\r\n private contentPreviewApiEndpoint: string = \"view/v1/Preview\";\r\n\r\n /**\r\n * The template url for article images\r\n */\r\n private articleImageUrl: string = \"https://img-s-msn-com.akamaized.net/tenant/amp/entityid/${imageId}.img?h=100&w=100&m=6&q=60&u=t&o=t&l=f&f=png\";\r\n\r\n /**\r\n * The template url for provider logo images\r\n */\r\n private providerLogoUrl: string = \"https://img-s-msn-com.akamaized.net/tenant/amp/entityid/${logoId}.img?h=16&w=16&m=6&q=60&u=t&o=t&l=f&f=png\";\r\n\r\n /**\r\n * the ocid for request\r\n */\r\n private ocid: string = \"feeds\";\r\n\r\n /**\r\n * Initializes a new instance of the `ContentActionsToolbarServiceClient` class.\r\n * @constructor\r\n * @public\r\n * @param {any} fetchImpl - The fetch implementation\r\n */\r\n public constructor(private fetchImpl: any) {\r\n }\r\n\r\n /**\r\n * Get content preference initial state\r\n * @param {string} targetId target id\r\n */\r\n public async GetPreferenceInitialState(targetId: string): Promise {\r\n let initialState: Status = undefined;\r\n try {\r\n const response = await this.GetContentStatusRequest(targetId);\r\n const isLike = response && response[\"value\"] && response[\"value\"].find(obj => obj.actionType === \"Like\");\r\n const isDislike = response && response[\"value\"] && response[\"value\"].find(obj => obj.actionType === \"Dislike\");\r\n initialState = isLike ? Status.Like : (isDislike ? Status.DisLike : Status.None);\r\n } catch (error) {\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ContentActionsToolbarAppErrors.ContentActionsGetContentStatusActionError,\r\n message: \"Failed obtaining content status\",\r\n pb: {\r\n ...ContentActionsToolbarAppErrors.ContentActionsGetContentStatusActionError.pb,\r\n customMessage: `Error: ${error}`\r\n }\r\n });\r\n }\r\n return initialState;\r\n }\r\n\r\n /**\r\n * Get required document data\r\n * @param {string} targetId target id\r\n */\r\n public async GetDocumentData(targetId: string): Promise {\r\n let documentData: DocumentData = undefined;\r\n try {\r\n const contentPreviewData = await this.GetContentPreviewData(targetId);\r\n documentData = this.TranslateContentPreviewDocumentData(contentPreviewData);\r\n if (!documentData) {\r\n throw new Error(`Failed to map content preview data to DocumentData. TargetId: ${targetId}`);\r\n }\r\n } catch (error) {\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ContentActionsToolbarAppErrors.ContentActionsGetDocumentDataError,\r\n message: \"Failed obtaining document data\",\r\n pb: {\r\n ...ContentActionsToolbarAppErrors.ContentActionsGetDocumentDataError.pb,\r\n customMessage: `Error: ${error}`\r\n }\r\n });\r\n }\r\n return documentData;\r\n }\r\n\r\n /**\r\n * The dislike target service call\r\n * @param targetId target id to be disliked\r\n */\r\n public async Dislike(targetId: string): Promise {\r\n return this.PostContentActionRequest(targetId, \"Dislike\");\r\n }\r\n\r\n /**\r\n * The undislike target service call\r\n * @param targetId target id to be undislike\r\n */\r\n public async Undislike(targetId: string): Promise {\r\n return this.DeleteContentActionRequest(targetId, \"Dislike\");\r\n }\r\n\r\n /**\r\n * The like target service call\r\n * @param targetId target id to be like\r\n */\r\n public async Like(targetId: string): Promise {\r\n return this.PostContentActionRequest(targetId, \"Like\");\r\n }\r\n\r\n /**\r\n * The like target service call\r\n * @param targetId target id to be like\r\n */\r\n public async Unlike(targetId: string): Promise {\r\n return this.DeleteContentActionRequest(targetId, \"Like\");\r\n }\r\n\r\n /**\r\n * Set request to service to get the metadata about content status\r\n * @param targetId target id\r\n */\r\n private async GetContentStatusRequest(targetId: string): Promise {\r\n const requestParams = OneServiceUtility.getBaseRequestData(\"GET\");\r\n requestParams.credentials = headData.UserIsSignedIn ? \"include\" : undefined;\r\n\r\n const serviceUrl = getServiceUrlForSubpath(this.contentActionsServiceEndpoint);\r\n const commonParams = OneServiceUtility.getCommonParams(this.ocid);\r\n [\r\n ...commonParams,\r\n {\r\n key: \"$filter\",\r\n value: `targetId eq '${targetId}'`\r\n }\r\n ].forEach(pair => pair.value && serviceUrl.searchParams.set(pair.key, pair.value));\r\n\r\n let contentStatusData: any;\r\n try {\r\n contentStatusData = await (sendRequest(\r\n async () => {\r\n const response: Response = await this.fetchImpl(serviceUrl.href, requestParams);\r\n if (response.status >= 400) {\r\n throw new Error(response.statusText);\r\n }\r\n return response.json();\r\n },\r\n `getContentAction`\r\n ));\r\n } catch (error) {\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ContentActionsToolbarAppErrors.ContentActionsContentStatusFetchError,\r\n message: \"Failed to fetch from content status data endpoint\",\r\n pb: {\r\n ...ContentActionsToolbarAppErrors.ContentActionsContentStatusFetchError.pb,\r\n customMessage: `Service URL: ${serviceUrl}, error: ${error}`\r\n }\r\n });\r\n }\r\n\r\n return contentStatusData;\r\n }\r\n\r\n /**\r\n * Gets article content data from ContentPreview endpoint\r\n * @param articleId the article id\r\n * @returns Primise The article details data\r\n */\r\n private async GetContentPreviewData(articleId: string): Promise {\r\n const requestParams = OneServiceUtility.getBaseRequestData(\"GET\");\r\n requestParams.credentials = headData.UserIsSignedIn ? \"include\" : undefined;\r\n\r\n // Build the url\r\n const serviceUrl = new URL(`${this.contentPreviewApiEndpoint}/${articleId}${appEnvironment.ContentServiceUrlBase.search}`, appEnvironment.ContentServiceUrlBase);\r\n\r\n let contentPreviewData: any;\r\n try {\r\n contentPreviewData = await (sendRequest(\r\n async () => {\r\n const response: Response = await this.fetchImpl(serviceUrl.href, requestParams);\r\n if (response.status >= 400) {\r\n throw new Error(response.statusText);\r\n }\r\n return response.json();\r\n },\r\n `getContentAction`\r\n ));\r\n } catch (error) {\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ContentActionsToolbarAppErrors.ContentActionsContentPreviewFetchError,\r\n message: \"Failed to fetch from content views data endpoint\",\r\n pb: {\r\n ...ContentActionsToolbarAppErrors.ContentActionsContentPreviewFetchError.pb,\r\n customMessage: `Service URL: ${serviceUrl}, error: ${error}`\r\n }\r\n });\r\n }\r\n\r\n return contentPreviewData;\r\n }\r\n\r\n /**\r\n * Delete an action from target\r\n * @param targetId target to be deleted\r\n * @param actionType type of the action\r\n */\r\n private async DeleteContentActionRequest(targetId: string, actionType: string): Promise {\r\n const requestParams = OneServiceUtility.getBaseRequestData(\"DELETE\");\r\n requestParams.credentials = headData.UserIsSignedIn ? \"include\" : undefined;\r\n\r\n const deleteQueryParam: KeyValuePair = {\r\n key: oneServiceQueryStringKeys.filter,\r\n value: `actionType eq '${actionType}' and targetId eq '${targetId}'`\r\n };\r\n\r\n const serviceUrl = getServiceUrlForSubpath(this.contentActionsServiceEndpoint);\r\n const commonParams = OneServiceUtility.getCommonParams(this.ocid);\r\n [\r\n deleteQueryParam,\r\n ...commonParams\r\n ].forEach((pair) => pair.value && serviceUrl.searchParams.set(pair.key, pair.value));\r\n\r\n let deleteResponse: Response;\r\n try {\r\n deleteResponse = await (sendRequest(\r\n async () => {\r\n const response: Response = await this.fetchImpl(serviceUrl.href, requestParams);\r\n if (response.status >= 400) {\r\n throw new Error(response.statusText);\r\n }\r\n return response;\r\n },\r\n `deleteContentAction${actionType}`\r\n ));\r\n } catch (error) {\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ContentActionsToolbarAppErrors.ContentActionsDeleteActionError,\r\n message: \"Error while calling delete action for content actions toolbar\",\r\n pb: {\r\n ...ContentActionsToolbarAppErrors.ContentActionsDeleteActionError.pb,\r\n customMessage: `URL: ${serviceUrl.href}, error: ${error}`\r\n }\r\n });\r\n }\r\n\r\n return deleteResponse;\r\n }\r\n\r\n /**\r\n * create an action from target\r\n * @param targetId target to be created\r\n * @param actionType type of the action\r\n */\r\n private async PostContentActionRequest(targetId: string, actionType: string, targetType?: string): Promise {\r\n const requestParams: RequestInit = {\r\n method: \"POST\",\r\n body: JSON.stringify({\r\n actionType,\r\n targetId,\r\n targetType\r\n }),\r\n credentials: headData.UserIsSignedIn ? \"include\" : undefined,\r\n headers: OneServiceUtility.getOneServiceHeaders()\r\n };\r\n\r\n const serviceUrl = getServiceUrlForSubpath(this.contentActionsServiceEndpoint);\r\n const commonParams = OneServiceUtility.getCommonParams(this.ocid);\r\n commonParams.forEach((pair) => {\r\n pair.value && serviceUrl.searchParams.set(pair.key, pair.value);\r\n });\r\n\r\n let postResponse: Response;\r\n try {\r\n postResponse = await (sendRequest(\r\n async () => {\r\n const response: Response = await this.fetchImpl(serviceUrl.href, requestParams);\r\n if (response.status >= 400) {\r\n throw new Error(response.statusText);\r\n }\r\n return response;\r\n },\r\n `getContentAction${actionType}`\r\n ));\r\n } catch (error) {\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ContentActionsToolbarAppErrors.ContentActionsPostActionError,\r\n message: \"Error while posting action for content actions toolbar\",\r\n pb: {\r\n ...ContentActionsToolbarAppErrors.ContentActionsPostActionError.pb,\r\n customMessage: `URL: ${serviceUrl.href}, error: ${error}`\r\n }\r\n });\r\n }\r\n\r\n return postResponse;\r\n }\r\n\r\n /**\r\n * Schema Translator for content preview data\r\n * @param {any} articleDataResponse response data from content preview api\r\n * @returns {DocumentData} translated document data\r\n */\r\n private TranslateContentPreviewDocumentData(articleDataResponse: any): DocumentData {\r\n const articleImageId = get(articleDataResponse, \"images[0].id\", undefined);\r\n const providerLogoId = get(articleDataResponse, \"provider.logo.id\", undefined);\r\n\r\n return {\r\n articleTitle: get(articleDataResponse, \"title\", undefined),\r\n articleImageUrl: articleImageId ? this.articleImageUrl.replace(\"${imageId}\", articleImageId) : undefined,\r\n providerName: get(articleDataResponse, \"provider.name\", undefined),\r\n providerLogoUrl: providerLogoId ? this.providerLogoUrl.replace(\"${logoId}\", providerLogoId) : undefined\r\n };\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ButtonItemType, ButtonType } from \"./components/sharing-toolbar/SharingToolbar\";\r\nimport { LikeDislikeActionKey, TelemetryConstants } from \"./ContentActionsToolbar.constants\";\r\nimport { OptionItemDislike, OptionItemLike, OptionItemUndoDislike, OptionItemUndoLike } from \"./components/sharing-toolbar/SharingToolbar.constants\";\r\nimport { SocialMediaItemConfigAttributes, SocialMediaTarget, ViewsUtility } from \"@msnews/views-helpers\";\r\nimport { Telemetry, TelemetryProps, TelemetryTypes } from \"@msnews/experiences-base\";\r\n\r\nimport { Status } from \".\";\r\nimport { TelemetryBase } from \"@msnews/core\";\r\n\r\n/**\r\n * Helper class to implement telemetry for content actions toolbar\r\n * @export\r\n * @class\r\n */\r\nexport class ContentActionsToolbarTelemetryHelper {\r\n\r\n /**\r\n * Injects telemetry data into sharing buttons array\r\n * @param {ButtonItemType[]} sharingButtons The sharing buttons array\r\n * @param {Status} status The current content status\r\n * @param {TelemetryProps} sharingToolbarTelemetryProps The sharing toolbar telemetry props\r\n * @param {TrackTelemetryEventSignature} handleTelemetryCall Dispatches click telemetry events\r\n */\r\n public static InjectTelemetry(sharingButtons: ButtonItemType[], status: Status, sharingToolbarTelemetryProps: TelemetryProps): void {\r\n sharingButtons.map(button => {\r\n let buttonTelemetryName: string;\r\n switch (button.buttonType) {\r\n case ButtonType.SocialMedia:\r\n buttonTelemetryName = button.buttonData.mediaType.toUpperCase();\r\n button.buttonData.newWindowTelemetryCall = (event: any) => {\r\n TelemetryBase.trackEvent({ type: \"click\", target: event.currentTarget }, null, null, buttonTelemetryName);\r\n return;\r\n };\r\n break;\r\n case ButtonType.ShareDialog:\r\n if (button.buttonData.shareDialogProps && button.buttonData.shareDialogProps.socialMediaItems) {\r\n buttonTelemetryName = button.buttonType.toUpperCase();\r\n let { shareDialogProps } = button.buttonData;\r\n button.buttonData.onSelect = (event: any) => {\r\n TelemetryBase.trackEvent({ type: \"click_nonnav\", target: event.currentTarget }, null, null, buttonTelemetryName);\r\n return;\r\n };\r\n if (button.buttonData.target === SocialMediaTarget.newWindow) {\r\n button.buttonData.newWindowTelemetryCall = (event: any) => {\r\n TelemetryBase.trackEvent({ type: \"click\", target: event.currentTarget }, null, null, buttonTelemetryName);\r\n return;\r\n };\r\n }\r\n\r\n let mediaTelemetryProps: { [s: string]: TelemetryProps } = shareDialogProps.socialMediaItems.reduce(\r\n (result, value) => {\r\n if (value) {\r\n result[value.toLowerCase()] = Telemetry.getChildTelemetryItem(sharingToolbarTelemetryProps, value.toUpperCase(), TelemetryTypes.Share);\r\n result[value.toLowerCase()].userFacingText = `tmx-stb-sd-${value.toLowerCase()}`;\r\n }\r\n return result;\r\n },\r\n {}\r\n );\r\n shareDialogProps.copyButtonTelemetryProps = Telemetry.getChildTelemetryItem(sharingToolbarTelemetryProps, TelemetryConstants.copyLinkTelemetryName, TelemetryTypes.Share);\r\n const closeButtonTelemetryProps = Telemetry.getChildTelemetryItem(sharingToolbarTelemetryProps, TelemetryConstants.closeDialogTelemetryName, TelemetryTypes.Close);\r\n shareDialogProps.closeButtonTelemetryTags = Telemetry.render(closeButtonTelemetryProps);\r\n shareDialogProps.shareIconTelemetryProps = mediaTelemetryProps;\r\n shareDialogProps.socialMediaConfigOverride = shareDialogProps.socialMediaItems.reduce((result, mediaItem) => {\r\n let mediaItemOverride: SocialMediaItemConfigAttributes = {};\r\n if (shareDialogProps.socialMediaConfigOverride && shareDialogProps.socialMediaConfigOverride[mediaItem]) {\r\n mediaItemOverride = {...shareDialogProps.socialMediaConfigOverride[mediaItem]};\r\n }\r\n mediaItemOverride.newWindowTelemetryCall = event => TelemetryBase.trackEvent({ type: \"click\", target: event.currentTarget }, null, null, mediaItem.toUpperCase());\r\n result[mediaItem] = mediaItemOverride;\r\n return result;\r\n }, {}\r\n );\r\n const shareDialogTelemetryProps = Telemetry.getChildTelemetryItem(sharingToolbarTelemetryProps, TelemetryConstants.shareDialogTelemetryName, TelemetryTypes.Interaction);\r\n button.buttonData.shareDialogProps = {\r\n ...shareDialogProps,\r\n ...Telemetry.render(shareDialogTelemetryProps)\r\n\r\n };\r\n button.buttonData.articleTelemetryTags = Telemetry.render(Telemetry.getChildTelemetryItem(sharingToolbarTelemetryProps, TelemetryConstants.shareArticleTelemetryName, TelemetryTypes.Share));\r\n }\r\n break;\r\n case ButtonType.LikeDislike:\r\n if (status === Status.Like) {\r\n buttonTelemetryName = OptionItemUndoLike.key.toUpperCase();\r\n } else if (status === Status.DisLike) {\r\n buttonTelemetryName = OptionItemUndoDislike.key.toUpperCase();\r\n } else {\r\n buttonTelemetryName = OptionItemLike.key.toUpperCase();\r\n }\r\n break;\r\n case ButtonType.MoreOptions:\r\n buttonTelemetryName = button.buttonType.toUpperCase();\r\n const menuItems = button.buttonData.menuItems;\r\n if (status === Status.Like) {\r\n menuItems.find(e => e.key === LikeDislikeActionKey.undoliked).telemetryTag = Telemetry.render(Telemetry.getChildTelemetryItem(sharingToolbarTelemetryProps, OptionItemUndoLike.key.toUpperCase(), TelemetryTypes.Unlike));\r\n menuItems.find(e => e.key === LikeDislikeActionKey.dislike).telemetryTag = Telemetry.render(Telemetry.getChildTelemetryItem(sharingToolbarTelemetryProps, OptionItemDislike.key.toUpperCase(), TelemetryTypes.Dislike));\r\n } else if (status === Status.DisLike) {\r\n menuItems.find(e => e.key === LikeDislikeActionKey.undodisliked).telemetryTag = Telemetry.render(Telemetry.getChildTelemetryItem(sharingToolbarTelemetryProps, OptionItemUndoDislike.key.toUpperCase(), TelemetryTypes.Undislike));\r\n menuItems.find(e => e.key === LikeDislikeActionKey.like).telemetryTag = Telemetry.render(Telemetry.getChildTelemetryItem(sharingToolbarTelemetryProps, OptionItemLike.key.toUpperCase(), TelemetryTypes.Like));\r\n } else {\r\n menuItems.find(e => e.key === LikeDislikeActionKey.dislike).telemetryTag = Telemetry.render(Telemetry.getChildTelemetryItem(sharingToolbarTelemetryProps, OptionItemDislike.key.toUpperCase(), TelemetryTypes.Dislike));\r\n }\r\n break;\r\n default:\r\n break;\r\n }\r\n button.telemetryTags = Telemetry.render(ViewsUtility.getChildTelemetryItem(sharingToolbarTelemetryProps, buttonTelemetryName, TelemetryTypes.Share));\r\n if (button.telemetryTags) {\r\n // Keeping same telemetry headline data as found today in Prime for AB testing\r\n button.telemetryTags[\"data-hl\"] = `tmx-stb-${buttonTelemetryName.toLowerCase()}`;\r\n }\r\n });\r\n }\r\n\r\n}\r\n","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { BreakpointIndexToPx, LikeDislikeActionKey, Status, TelemetryConstants } from \"./ContentActionsToolbar.constants\";\r\nimport { BreakpointTracker, identifyBreakpoint } from \"@microsoft/fast-layouts-react\";\r\nimport { ButtonItemType, ButtonType } from \"./components/sharing-toolbar/SharingToolbar\";\r\nimport { ContentActionsToolbarActions, ContentActionsToolbarConfig, ContentActionsToolbarProps, ContentActionsToolbarState } from \".\";\r\nimport { ContentActionsToolbarInspector, ContentActionsToolbarInspectorArgs } from \"./ContentActionsToolbar.inspector\";\r\nimport { DynamicReducer, IReducer } from \"@msnews/experiences-redux\";\r\nimport { ExperienceInitialProps, Telemetry, TelemetryProps, TelemetryTags, TelemetryTypes } from \"@msnews/experiences-base\";\r\nimport { InspectorResponse, TelemetryBase, getAppEnvironment } from \"@msnews/core\";\r\nimport { OptionItemDislike, OptionItemLike, OptionItemUndoDislike, OptionItemUndoLike } from \"./components/sharing-toolbar/SharingToolbar.constants\";\r\nimport { SharedDocumentType, SharingHelper, ViewsStringResource } from \"@msnews/views-helpers\";\r\n\r\nimport { ComponentConnector } from \"@msnews/experiences-connector\";\r\nimport { ContentActionsToolbarAppErrors } from \"@msnews/diagnostics\";\r\nimport { ContentActionsToolbarServiceClient } from \"./services\";\r\nimport { ContentActionsToolbarTelemetryHelper } from \"./ContentActionsToolbar.telemetry\";\r\nimport { Store } from \"redux\";\r\nimport { getInnerWidth } from \"@msnews/isomorphic-util\";\r\n\r\n/**\r\n * An interface to represent the more options menu callbacks\r\n * @interface MoreOptionsCallbacks\r\n */\r\ninterface MoreOptionsCallbacks {\r\n /** On like event handler */\r\n onLike: (event: any) => void;\r\n\r\n /** On dislike evewnt hander */\r\n onDislike: (event: any) => void;\r\n}\r\n\r\n/**\r\n * The connector for the ContentActionsToolbar Experience\r\n * @class\r\n */\r\nexport class ContentActionsToolbarConnector extends ComponentConnector {\r\n\r\n /**\r\n * Telemetry related props for the experience.\r\n * @type {TelemetryProps}\r\n */\r\n private sharingToolbarTelemetryProps: TelemetryProps;\r\n\r\n /**\r\n * Telemetry related tags for the experience.\r\n * @type {TelemetryProps}\r\n */\r\n private sharingToolbarTelemetryTags: TelemetryTags;\r\n\r\n /**\r\n * An instance of the content action service client\r\n * @type {ContentActionsToolbarServiceClient}\r\n */\r\n private actionServiceClient: ContentActionsToolbarServiceClient;\r\n\r\n /**\r\n * Telemetry related tags for the more option button.\r\n */\r\n private moreOptionsTelemetryTags: {\r\n Like: TelemetryTags,\r\n Dislike: TelemetryTags,\r\n UndoLike: TelemetryTags,\r\n UndoDislike: TelemetryTags\r\n };\r\n\r\n /**\r\n * Initializes the ContentActionsToolbar connector\r\n * @param {string} namespace Redux subspace name for the connector\r\n * @param {string} parentNamespace Redux subspace name for the parent connector\r\n * @param {DynamicReducer} rootReducer Application root reducer\r\n * @param {IReducer} reducer The connector reducer\r\n * @param {Store} store The store or redux subspace that the connector will be connected to\r\n * @param {ContentActionsToolbarConfig} config The configuration properties from config index\r\n */\r\n public constructor( namespace: string,\r\n parentNamespace: string,\r\n rootReducer: DynamicReducer,\r\n reducer: IReducer,\r\n store: Store,\r\n config?: ContentActionsToolbarConfig) {\r\n super(namespace, parentNamespace, rootReducer, reducer, store, config);\r\n }\r\n\r\n /**\r\n * State mapper\r\n * @param state The current state for the connector\r\n */\r\n public mapStateToProps(state: ContentActionsToolbarState): ContentActionsToolbarProps {\r\n const inspectorArgs: ContentActionsToolbarInspectorArgs = {\r\n config: this.config,\r\n children: {},\r\n state: state\r\n };\r\n\r\n let contentActionsToolbarProps: ContentActionsToolbarProps = {};\r\n\r\n if (state.status && state.documentId && state.documentData) {\r\n const inspectorResponse: InspectorResponse = ContentActionsToolbarInspector.inspect(inspectorArgs);\r\n\r\n const status = inspectorResponse.props.contentStatus;\r\n const callbacks = this.BuildLikeDislikeCallbacks(status, state.documentId);\r\n\r\n if (inspectorResponse.props.sharingToolbar && inspectorResponse.props.sharingToolbar.sharingButtons && inspectorResponse.props.sharingToolbar.sharingButtons.length > 0) {\r\n const sharingButtons = inspectorResponse.props.sharingToolbar.sharingButtons;\r\n\r\n this.InjectCallbacksToMoreOptionsMenu(sharingButtons.find(m => m.buttonType === ButtonType.MoreOptions), status, callbacks);\r\n\r\n ContentActionsToolbarTelemetryHelper.InjectTelemetry(sharingButtons, status, this.sharingToolbarTelemetryProps);\r\n\r\n const likeDislikeButton = sharingButtons.find(m => m.buttonType === ButtonType.LikeDislike);\r\n if (likeDislikeButton) {\r\n sharingButtons.find(m => m.buttonType === ButtonType.LikeDislike).buttonData\r\n .onSelect = (event: any) => status === Status.DisLike ? callbacks.onDislike(event) : callbacks.onLike(event);\r\n }\r\n }\r\n\r\n contentActionsToolbarProps = {\r\n ...inspectorResponse.props,\r\n rootTelemetryTags: this.sharingToolbarTelemetryTags,\r\n ...this.telemetryTags,\r\n ...callbacks\r\n };\r\n }\r\n\r\n return contentActionsToolbarProps;\r\n }\r\n\r\n /**\r\n * Perform one time initialization of the connector, including getting initial state from config\r\n * @param {ExperienceInitialProps} connectorProps Application initial props\r\n */\r\n public async onComponentConnect(initialProps?: ExperienceInitialProps): Promise {\r\n await ComponentConnector.prototype.onComponentConnect.call(this, initialProps);\r\n\r\n const { contentId, context: { staticPosition, isRSThree = false, documentType = SharedDocumentType.CMS } } = initialProps;\r\n if (!contentId) {\r\n ContentActionsToolbarActions.sharingToolbarError.getActionSender(this).send(new Error(ViewsStringResource.sharingToolbarLoadFailure));\r\n this.onAppError({\r\n ...ContentActionsToolbarAppErrors.ContentActionsSharingToolbarLoadError,\r\n message: `Error while initializing content actions toolbar. Requried initial props is not available: InitialProps = ${initialProps}`\r\n });\r\n return;\r\n }\r\n\r\n this.actionServiceClient = new ContentActionsToolbarServiceClient(window.fetch.bind(window));\r\n\r\n this.generateTelemetryTags();\r\n\r\n this.getContentStatus(contentId);\r\n this.getDocumentData(contentId, documentType);\r\n\r\n const currentBreakpoint = this.initializeBreakpointTracker(isRSThree);\r\n ContentActionsToolbarActions.initializeToolbar.getActionSender(this).send(currentBreakpoint, isRSThree, contentId, staticPosition);\r\n }\r\n\r\n /**\r\n * Initialize and subscribe Breakpoint tracker to detect change in toolbar position\r\n */\r\n private initializeBreakpointTracker(isRSThree: boolean): number {\r\n BreakpointTracker.defaultBreakpoint = identifyBreakpoint(getInnerWidth());\r\n BreakpointTracker.breakpoints = BreakpointIndexToPx;\r\n BreakpointTracker.update();\r\n BreakpointTracker.subscribe(breakpoint => {\r\n ContentActionsToolbarActions.ViewportUpdate.getActionSender(this).send(breakpoint, isRSThree);\r\n });\r\n\r\n return BreakpointTracker.currentBreakpoint();\r\n }\r\n\r\n /**\r\n * Fetches the current status (like/dislike/none) of the document\r\n * @param {ExperienceInitialProps} documentId The document Id\r\n */\r\n private async getContentStatus(documentId: string): Promise {\r\n const contentStatus = await this.actionServiceClient.GetPreferenceInitialState(documentId);\r\n if (!contentStatus) {\r\n ContentActionsToolbarActions.sharingToolbarError.getActionSender(this).send(new Error(ViewsStringResource.sharingToolbarLoadFailure));\r\n this.onAppError({\r\n ...ContentActionsToolbarAppErrors.ContentActionsSharingToolbarLoadError,\r\n message: `Error while retrieving content status data from API`\r\n });\r\n return;\r\n }\r\n ContentActionsToolbarActions.ContentStatuReady.getActionSender(this).send(contentStatus);\r\n }\r\n\r\n /**\r\n * Fetches the required document data for the experience\r\n * @param {ExperienceInitialProps} documentId The document Id\r\n */\r\n private async getDocumentData(documentId: string, documentType: SharedDocumentType): Promise {\r\n let documentData = await this.actionServiceClient.GetDocumentData(documentId);\r\n if (!documentData) {\r\n ContentActionsToolbarActions.sharingToolbarError.getActionSender(this).send(new Error(ViewsStringResource.sharingToolbarLoadFailure));\r\n this.onAppError({\r\n ...ContentActionsToolbarAppErrors.ContentActionsSharingToolbarLoadError,\r\n message: `Error while retrieving content status data from API`\r\n });\r\n return;\r\n }\r\n\r\n documentData.sharingShortUrl = SharingHelper.shortUrlBuilder({documentId, documentType}, getAppEnvironment().CurrentMarket);\r\n ContentActionsToolbarActions.documentDataReady.getActionSender(this).send(documentData);\r\n }\r\n\r\n /**\r\n * Builds the like and dislike callbacks\r\n * @param {Status} The content status\r\n * @param {DocumentId} The document id\r\n * @returns {MoreOptionsCallbacks} The MoreOptionsCallbacks interface implementation\r\n */\r\n private BuildLikeDislikeCallbacks(status: Status, documentId: string): MoreOptionsCallbacks {\r\n return {\r\n onLike: (event: Event) => {\r\n if (status !== Status.Like) {\r\n this.actionServiceClient.Like(documentId);\r\n TelemetryBase.trackEvent({ type: \"click_nonnav\", target: event.currentTarget }, null, null, OptionItemLike.key.toUpperCase());\r\n ContentActionsToolbarActions.likeContent.getActionSender(this).send();\r\n } else {\r\n this.actionServiceClient.Unlike(documentId);\r\n TelemetryBase.trackEvent({ type: \"click_nonnav\", target: event.currentTarget }, null, null, OptionItemUndoLike.key.toUpperCase());\r\n ContentActionsToolbarActions.unlikeContent.getActionSender(this).send();\r\n }\r\n return;\r\n },\r\n onDislike: (event: Event) => {\r\n if (status !== Status.DisLike) {\r\n this.actionServiceClient.Dislike(documentId);\r\n TelemetryBase.trackEvent({ type: \"click_nonnav\", target: event.currentTarget }, null, null, OptionItemDislike.key.toUpperCase());\r\n ContentActionsToolbarActions.dislikeContent.getActionSender(this).send();\r\n } else {\r\n this.actionServiceClient.Undislike(documentId);\r\n TelemetryBase.trackEvent({ type: \"click_nonnav\", target: event.currentTarget }, null, null, OptionItemUndoDislike.key.toUpperCase());\r\n ContentActionsToolbarActions.undislikeContent.getActionSender(this).send();\r\n }\r\n return;\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * Injects callbacks to more options menu buttons\r\n * @param {ButtonItemType} moreOptionsButton The more option button\r\n * @param {Status} status The current content status\r\n * @param {MoreOptionsCallbacks} The more options menu callbacks interface\r\n */\r\n private InjectCallbacksToMoreOptionsMenu(moreOptionsButton: ButtonItemType, status: Status, callbacks: MoreOptionsCallbacks): void {\r\n if (!moreOptionsButton || !moreOptionsButton.buttonData || !moreOptionsButton.buttonData.menuItems) {\r\n return;\r\n }\r\n const { menuItems } = moreOptionsButton.buttonData;\r\n\r\n if (status === Status.Like) {\r\n menuItems.find(e => e.key === LikeDislikeActionKey.undoliked).onSelect = (event: any) => callbacks.onLike(event);\r\n menuItems.find(e => e.key === LikeDislikeActionKey.dislike).onSelect = (event: any) => callbacks.onDislike(event);\r\n } else if (status === Status.DisLike) {\r\n menuItems.find(e => e.key === LikeDislikeActionKey.undodisliked).onSelect = (event: any) => callbacks.onDislike(event);\r\n menuItems.find(e => e.key === LikeDislikeActionKey.like).onSelect = (event: any) => callbacks.onLike(event);\r\n } else {\r\n menuItems.find(e => e.key === LikeDislikeActionKey.dislike).onSelect = (event: any) => callbacks.onDislike(event);\r\n }\r\n }\r\n\r\n /**\r\n * Sets base telemetry data for Content Actions Toolbar\r\n */\r\n private generateTelemetryTags(): void {\r\n this.sharingToolbarTelemetryProps = Telemetry.getChildTelemetryItem(this.telemetryProps, TelemetryConstants.socialToolbarTelemetryName, TelemetryTypes.Module);\r\n this.sharingToolbarTelemetryTags = Telemetry.render(this.sharingToolbarTelemetryProps);\r\n this.moreOptionsTelemetryTags = {\r\n Like: Telemetry.render(Telemetry.getChildTelemetryItem(this.sharingToolbarTelemetryProps, OptionItemLike.key.toUpperCase(), TelemetryTypes.Like)),\r\n Dislike: Telemetry.render(Telemetry.getChildTelemetryItem(this.sharingToolbarTelemetryProps, OptionItemDislike.key.toUpperCase(), TelemetryTypes.Dislike)),\r\n UndoLike: Telemetry.render(Telemetry.getChildTelemetryItem(this.sharingToolbarTelemetryProps, OptionItemUndoLike.key.toUpperCase(), TelemetryTypes.Unlike)),\r\n UndoDislike: Telemetry.render(Telemetry.getChildTelemetryItem(this.sharingToolbarTelemetryProps, OptionItemUndoDislike.key.toUpperCase(), TelemetryTypes.Undislike))\r\n };\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { CommonExperienceProps, TelemetryTags } from \"@msnews/experiences-base\";\r\n\r\nimport { AppError } from \"@msnews/diagnostics\";\r\nimport { ContentActionsToolbarClassNames } from \".\";\r\nimport { ManagedClasses } from \"@microsoft/fast-components-class-name-contracts-msft\";\r\nimport { SharingToolbarProps } from \"./components/sharing-toolbar\";\r\nimport { Status } from \"./ContentActionsToolbar.constants\";\r\n\r\n/**\r\n * Toolbar positioning options\r\n */\r\nexport enum ToolbarPosition {\r\n horizontal = \"horizontal\",\r\n vertical = \"vertical\"\r\n}\r\n\r\n/**\r\n * An interface to represent the ContentActionsToolbar jss managed classes.\r\n * @export\r\n * @interface ContentActionsToolbarManagedClasses\r\n */\r\nexport interface ContentActionsToolbarManagedClasses extends ManagedClasses { }\r\n\r\n/**\r\n * An interface to represent the ContentActionsToolbar handled props.\r\n * @export\r\n * @interface ContentActionsToolbarHandledProps\r\n */\r\nexport interface ContentActionsToolbarHandledProps extends CommonExperienceProps, ContentActionsToolbarManagedClasses {\r\n /**\r\n * Defines the toolbar position in case of single static position. Undefined otherwise.\r\n */\r\n staticPosition?: ToolbarPosition;\r\n\r\n /**\r\n * Position to render toolbar in\r\n * @type {ToolbarPosition}\r\n */\r\n position?: ToolbarPosition;\r\n\r\n /**\r\n * Sharing toolbar props\r\n * @type {SharingToolbarProps}\r\n */\r\n sharingToolbar?: SharingToolbarProps;\r\n\r\n /**\r\n * Content Status\r\n * @type {Status}\r\n */\r\n contentStatus?: Status;\r\n\r\n /**\r\n * Sharing toolbar error\r\n * @type {Error}\r\n */\r\n sharingError?: Error;\r\n\r\n /**\r\n * Root element telemetry tags\r\n * @type {TelemetryTags}\r\n */\r\n rootTelemetryTags?: TelemetryTags;\r\n}\r\n\r\n/**\r\n * An interface to represent the ContentActionsToolbar unhandled props.\r\n * @export\r\n * @interface ContentActionsToolbarUnhandledProps\r\n */\r\nexport interface ContentActionsToolbarUnhandledProps extends React.HTMLAttributes {}\r\n\r\n/**\r\n * The ContentActionsToolbar props type\r\n */\r\nexport type ContentActionsToolbarProps = ContentActionsToolbarHandledProps & ContentActionsToolbarUnhandledProps;\r\n\r\n/**\r\n * App Error Event Tracking Callback Signature\r\n */\r\nexport type TrackAppErrorEventSignature = (error: AppError) => void;\r\n\r\n/**\r\n * Click event tracking callback signature\r\n */\r\nexport type TrackTelemetryEventSignature = (event: Object, element: HTMLElement, destination: string, headline: string) => void;","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ActionHandler, IActionPayload, IReducer } from \"@msnews/experiences-redux\";\r\nimport { ContentActionsToolbarActions, ContentActionsToolbarState, ToolbarPosition } from \".\";\r\nimport { Status, ToolbarBreakpoints } from \"./ContentActionsToolbar.constants\";\r\n\r\nimport { DocumentData } from \"./ContentActionsToolbar.state\";\r\n\r\n/**\r\n * Experience initial state.\r\n */\r\nconst initialState: ContentActionsToolbarState = {\r\n documentData: undefined,\r\n documentId: undefined,\r\n position: undefined,\r\n sharingError: undefined,\r\n staticPosition: undefined,\r\n status: undefined\r\n};\r\n\r\n/**\r\n * The reducer for the ContentActionsToolbar connector, and the ContentActionsToolbarState\r\n * @export\r\n * @class\r\n */\r\nexport class ContentActionsToolbarReducer implements IReducer {\r\n /**\r\n * Update the state for the connector, based on the action being applied\r\n * @param state The previous state\r\n * @param actionPayload The action being applied\r\n */\r\n public reduce(state: ContentActionsToolbarState, actionPayload: IActionPayload): ContentActionsToolbarState {\r\n // Return the initial state for this experience, including the config.\r\n if (!state) {\r\n return initialState;\r\n }\r\n\r\n // Return the passed in state, if there is no action specified\r\n if (!actionPayload) {\r\n return state;\r\n }\r\n\r\n let newState: ContentActionsToolbarState;\r\n\r\n // handle actions\r\n ActionHandler.handleAction(actionPayload, ContentActionsToolbarActions.initializeToolbar, (breakpointIndex: number,\r\n isRSThreeDevice: boolean,\r\n documentId: string,\r\n staticPosition: ToolbarPosition) => {\r\n newState = initialState;\r\n newState.position = this.getToolbarPosition(staticPosition, isRSThreeDevice, breakpointIndex);\r\n newState.documentId = documentId;\r\n newState.staticPosition = staticPosition;\r\n });\r\n\r\n ActionHandler.handleAction(actionPayload, ContentActionsToolbarActions.ContentStatuReady, (status: Status) => {\r\n newState = {\r\n ...state,\r\n status\r\n };\r\n });\r\n\r\n ActionHandler.handleAction(actionPayload, ContentActionsToolbarActions.documentDataReady, (documentData: DocumentData) => {\r\n newState = {\r\n ...state,\r\n documentData\r\n };\r\n });\r\n\r\n ActionHandler.handleAction(actionPayload, ContentActionsToolbarActions.likeContent, () => {\r\n newState = {\r\n ...state,\r\n status: Status.Like\r\n };\r\n });\r\n\r\n ActionHandler.handleAction(actionPayload, ContentActionsToolbarActions.unlikeContent, () => {\r\n newState = {\r\n ...state,\r\n status: Status.None\r\n };\r\n });\r\n\r\n ActionHandler.handleAction(actionPayload, ContentActionsToolbarActions.dislikeContent, () => {\r\n newState = {\r\n ...state,\r\n status: Status.DisLike\r\n };\r\n });\r\n\r\n ActionHandler.handleAction(actionPayload, ContentActionsToolbarActions.undislikeContent, () => {\r\n newState = {\r\n ...state,\r\n status: Status.None\r\n };\r\n });\r\n\r\n ActionHandler.handleAction(actionPayload, ContentActionsToolbarActions.ViewportUpdate, (breakpointIndex: number, isRSThreeDevice: boolean) => {\r\n newState = {\r\n ...state,\r\n position: this.getToolbarPosition(state.staticPosition, isRSThreeDevice, breakpointIndex)\r\n };\r\n });\r\n\r\n ActionHandler.handleAction(actionPayload, ContentActionsToolbarActions.sharingToolbarError, (error: Error) => {\r\n newState = {\r\n ...state,\r\n sharingError: error\r\n };\r\n });\r\n\r\n return newState || state;\r\n }\r\n\r\n /**\r\n * Calculates current toolbar position\r\n * @param staticPosition Defines orientation for static position if single position. Undefined otherwise.\r\n * @param isRSThreeDevice Indicates if device is RSThree\r\n * @param breakpointIndex Current breakpoint index.\r\n * @returns Toolbar current position\r\n */\r\n private getToolbarPosition(staticPosition: ToolbarPosition, isRSThreeDevice: boolean, breakpointIndex: number): ToolbarPosition {\r\n if (staticPosition) {\r\n return staticPosition;\r\n } else {\r\n const currentBreakpointIndex = isRSThreeDevice ? ToolbarBreakpoints.Breakpoint3_2 : ToolbarBreakpoints.Breakpoint3_3;\r\n return breakpointIndex >= currentBreakpointIndex ? ToolbarPosition.vertical : ToolbarPosition.horizontal;\r\n }\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { DesignSystem, ElevationMultiplier, applyElevation, neutralFillActive, neutralFillHover, neutralForegroundRest, neutralLayerCard } from \"@microsoft/fast-components-styles-msft\";\r\nimport { applyLocalizedProperty, toPx } from \"@microsoft/fast-jss-utilities\";\r\nimport { iconContainerDefaultColor, likeDislikeIconBackroundColor, moreOptionsIconColors } from \"./SharingToolbar.constants\";\r\n\r\nimport { CardContextMenuClassNameContract } from \"@msnews/card-context-menu\";\r\nimport { ComponentStyles } from \"@microsoft/fast-jss-manager\";\r\nimport { SharingToolbarClassNames } from \"./\";\r\n\r\n// reduce listItem dimension to 32, remove margin for iconListHorizontal (3px) and add list icon margin (in between) dinamically hor/vert\r\nconst iconListItemDimension = 32;\r\nconst iconContainerDimension = 32;\r\nconst iconImageDimension = 18;\r\nconst iconPadding = 10;\r\n\r\n/**\r\n * The SharingToolbar styles\r\n * @type {ComponentStyles}\r\n */\r\nexport const SharingToolbarStyles: ComponentStyles = (config: DesignSystem) => {\r\n return {\r\n icon_none: {},\r\n icon_like: {},\r\n icon_dislike: {},\r\n iconListHorizontal: {\r\n \"list-style\": \"none\",\r\n padding: \"0\",\r\n margin: \"0\",\r\n \"text-align\": \"center\",\r\n \"& $iconListItem\": {\r\n [applyLocalizedProperty(\"margin-right\", \"margin-left\", config.direction)]: toPx(iconPadding)\r\n }\r\n },\r\n iconListVertical: {\r\n float: \"left\",\r\n height: \"auto\",\r\n width: toPx(iconListItemDimension),\r\n position: \"absolute\",\r\n \"& $iconListItem\": {\r\n \"margin-bottom\": toPx(iconPadding)\r\n }\r\n },\r\n iconListItem: {\r\n \"align-items\": \"center\",\r\n display: \"inline-flex\",\r\n height: toPx(iconListItemDimension),\r\n \"justify-content\": \"center\",\r\n width: toPx(iconListItemDimension),\r\n \"&:hover\": {\r\n cursor: \"pointer\"\r\n }\r\n },\r\n shareDialog: {\r\n \"background-color\": \"#f00\"\r\n },\r\n iconContainer: {\r\n cursor: \"pointer\",\r\n border: \"unset\",\r\n padding: \"unset\",\r\n \"background-color\": iconContainerDefaultColor,\r\n \"border-radius\": \"50%\",\r\n color: neutralForegroundRest,\r\n height: toPx(iconContainerDimension),\r\n \"justify-content\": \"center\",\r\n position: \"relative\",\r\n width: toPx(iconContainerDimension),\r\n \"$icon_none &\": {\r\n \"background-color\": likeDislikeIconBackroundColor.none\r\n },\r\n \"$icon_like &\": {\r\n \"background-color\": likeDislikeIconBackroundColor.like\r\n },\r\n \"$icon_dislike &\": {\r\n \"background-color\": likeDislikeIconBackroundColor.dislike\r\n },\r\n \"& img\": {\r\n \"vertical-align\": \"unset\"\r\n }\r\n },\r\n iconImage: {\r\n bottom: \"0\",\r\n left: \"0\",\r\n margin: \"7px\",\r\n right: \"0\",\r\n top: \"0\",\r\n height: toPx(iconImageDimension),\r\n width: toPx(iconImageDimension)\r\n },\r\n moreOptions: {\r\n height: toPx(iconContainerDimension),\r\n width: toPx(iconContainerDimension)\r\n }\r\n };\r\n};\r\n\r\n/**\r\n * The context menu styles\r\n * @type {ComponentStyles}\r\n */\r\nexport const contextMenuStyles: Partial> = {\r\n menuContainer: {\r\n \"background-color\": moreOptionsIconColors.background,\r\n \"border-radius\": \"50%\",\r\n height: toPx(iconContainerDimension),\r\n width: toPx(iconContainerDimension)\r\n },\r\n settingButton: {\r\n background: \"none\",\r\n border: \"0\",\r\n cursor: \"pointer\",\r\n display: \"flex\",\r\n padding: \"0\",\r\n height: toPx(iconContainerDimension),\r\n margin: \"0\",\r\n width: toPx(iconContainerDimension),\r\n \"& svg\": {\r\n color: moreOptionsIconColors.foreground,\r\n display: \"flex\",\r\n margin: \"auto\",\r\n height: \"inherit\",\r\n width: toPx(iconImageDimension),\r\n \"& path\": {\r\n fill: \"currentColor\"\r\n }\r\n }\r\n },\r\n contextMenu: {\r\n ...applyElevation(ElevationMultiplier.e11),\r\n \"background-color\": neutralLayerCard,\r\n border: \"none\",\r\n display: \"grid\",\r\n padding: \"8px 0\",\r\n margin: \"0 14px\",\r\n width: \"240px\"\r\n },\r\n contextMenuItem: {\r\n background: neutralLayerCard,\r\n \"box-sizing\": \"border-box\",\r\n border: \"none\",\r\n display: \"inline-block\",\r\n padding: \"6px 16px\",\r\n width: \"auto\",\r\n \"&:hover, &:focus\": {\r\n background: neutralFillHover(neutralLayerCard),\r\n border: \"none\"\r\n },\r\n \"&:active\": {\r\n background: neutralFillActive(neutralLayerCard)\r\n }\r\n },\r\n contextMenuItem_contentRegion: {\r\n color: neutralForegroundRest(neutralLayerCard),\r\n \"grid-column-start\": \"1\"\r\n }\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport * as React from \"react\";\r\n\r\nimport { ArticleCard, ArticleProviderProps } from \"@msnews/article-card\";\r\nimport {\r\n DialogArticleCardHandledProps,\r\n DialogArticleCardManagedClasses,\r\n DialogArticleCardUnhandledProps\r\n} from \"./DialogArticleCard.props\";\r\nimport { HeadingProps, HeadingSize, HeadingTag } from \"@microsoft/fast-components-react-msft\";\r\nimport { ImageResizeMode, ViewsImageData, ViewsUtility, defaultDpi, defaultImageQuality } from \"@msnews/views-helpers\";\r\nimport { TypographyProps, TypographySize, TypographyTag } from \"@microsoft/fast-components-react-base\";\r\n\r\nimport Foundation from \"@microsoft/fast-components-foundation-react\";\r\nimport { HandledPropsKeys } from \"@msnews/core\";\r\n\r\n/**\r\n * Image dimensions for article image layout\r\n */\r\nconst ArticleImageDimension = {\r\n height: 100,\r\n width: 100,\r\n resizeMode: ImageResizeMode.Scale,\r\n dpi: defaultDpi,\r\n quality: defaultImageQuality\r\n};\r\n\r\n/**\r\n * Dialog article card\r\n * @class - Dialog Article Card\r\n * @classdesc - An dialog article Card composed from the base article card.\r\n */\r\nexport class DialogArticleCard extends Foundation {\r\n /**\r\n * Handled props contract\r\n * @protected\r\n * @type { HandledPropsKeys }\r\n */\r\n protected handledProps: HandledPropsKeys = {\r\n anchorRef: undefined,\r\n articleId: undefined,\r\n headlineTitle: undefined,\r\n href: undefined,\r\n image: undefined,\r\n managedClasses: undefined,\r\n provider: undefined\r\n };\r\n\r\n /**\r\n * Constructs an DialogArticleCard component\r\n * @constructor\r\n * @param { DialogArticleCardHandledProps & DialogArticleCardManagedClasses } props props contract\r\n */\r\n constructor(props: DialogArticleCardHandledProps & DialogArticleCardManagedClasses) {\r\n super(props);\r\n }\r\n\r\n /**\r\n * Component rendered\r\n * @method\r\n * @returns {JSX.Element} the DialogArticleCard component\r\n */\r\n public render(): JSX.Element {\r\n let { href, image, managedClasses } = this.props;\r\n\r\n if (image && image.src) {\r\n const viewsImageData: ViewsImageData = {\r\n alt: image.alt || \"article headline image\",\r\n caption: \"image\",\r\n src: image.src\r\n };\r\n\r\n image.src = ViewsUtility.getResizedImageUrl(viewsImageData,\r\n ArticleImageDimension.width,\r\n ArticleImageDimension.height,\r\n ArticleImageDimension.dpi,\r\n ArticleImageDimension.resizeMode,\r\n ArticleImageDimension.quality);\r\n }\r\n\r\n const articleCard = (\r\n \r\n );\r\n\r\n if (image) {\r\n return (\r\n articleCard\r\n );\r\n } else {\r\n return (\r\n
    \r\n {articleCard}\r\n
    \r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Coerces the title props to enforce visual level\r\n * @method\r\n * @returns {HeadingProps} the headline title props\r\n */\r\n private coerceTitleProps(): any {\r\n const coercedProps: Partial = {\r\n size: HeadingSize._6,\r\n tag: HeadingTag.h3\r\n };\r\n\r\n return { ...this.props.headlineTitle, ...coercedProps };\r\n }\r\n\r\n /**\r\n * Coerces the provider props to enforce visual level of the name\r\n * @method\r\n * @returns {ArticleProviderProps} the provider props\r\n */\r\n private coerceProviderProps(): ArticleProviderProps {\r\n const { provider } = this.props;\r\n if (!provider) {\r\n return;\r\n }\r\n\r\n const coercedProviderNameProps: Partial = {\r\n size: TypographySize._8,\r\n tag: TypographyTag.h5\r\n };\r\n\r\n const coercedProps: Partial = {\r\n name: { ...provider.name, ...coercedProviderNameProps }\r\n };\r\n\r\n const coerceProviderProps = { ...provider, ...coercedProps };\r\n if (!coerceProviderProps.image || !coerceProviderProps.image.src) {\r\n coerceProviderProps.image = undefined;\r\n }\r\n\r\n return coerceProviderProps;\r\n }\r\n}\r\n\r\nexport * from \"./DialogArticleCard.props\";","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { applyFontWeightNormal, applyFontWeightSemiBold, applyTypeRampConfig, getLineHeight, neutralFillStealthRest, neutralForegroundHover } from \"@microsoft/fast-components-styles-msft\";\r\nimport { applyLocalizedProperty, applyMaxLines, toPx } from \"@microsoft/fast-jss-utilities\";\r\n\r\nimport { ComponentStyles } from \"@microsoft/fast-jss-manager\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { DialogArticleCardClassNameContract } from \"./DialogArticleCard.classnames\";\r\n\r\nconst ArticleCardImageBorderRadius = 2;\r\nconst RelatedCardHeight = 100;\r\nconst RelatedCardImageSize = 100;\r\nconst HeadlineTextMargin = 16;\r\n\r\nconst borderColor = \"rgba(0,0,0, 0.05)\";\r\nconst DialogArticleCardTypeRamp = \"t7\";\r\n\r\n/**\r\n * The DialogArticleCard styles\r\n * @type {ComponentStyles}\r\n */\r\nexport const DialogArticleCardStyles: ComponentStyles = (config: DesignSystem) => {\r\n return {\r\n articleCard: {\r\n background: \"none\",\r\n \"border-bottom\": `1px solid ${borderColor}`,\r\n cursor: \"pointer\",\r\n display: \"flex\",\r\n padding: \"15px 0\",\r\n position: \"relative\"\r\n },\r\n articleCard_content: {\r\n display: \"flex\",\r\n \"text-decoration\": \"none\",\r\n \"&:hover\": {\r\n \"& $articleCard_headline\": {\r\n color: neutralForegroundHover(neutralFillStealthRest),\r\n \"text-decoration\": \"underline\"\r\n },\r\n \"& $articleCard_imageOverlay\": {\r\n opacity: 0.1\r\n }\r\n }\r\n },\r\n articleCard_imageWrapper: {\r\n position: \"relative\",\r\n \"& $articleCard_image\": {\r\n height: toPx(RelatedCardImageSize)\r\n }\r\n },\r\n articleCard_image: {\r\n \"border-radius\": toPx(ArticleCardImageBorderRadius),\r\n \"object-fit\": \"cover\",\r\n width: toPx(RelatedCardImageSize)\r\n },\r\n articleCard_imageOverlay: {\r\n height: \"100%\",\r\n opacity: \"0\",\r\n position: \"absolute\",\r\n top: \"0\",\r\n width: \"100%\"\r\n },\r\n articleCard_textWrapper: {\r\n \"box-sizing\": \"border-box\",\r\n flex: \"1\",\r\n height: toPx(RelatedCardHeight),\r\n padding: applyLocalizedProperty(`0 0 0 ${toPx(HeadlineTextMargin)}`, `0 ${toPx(HeadlineTextMargin)} 0 0`, config.direction)\r\n },\r\n articleCard_headline: {\r\n \"& $articleCard_headlineText\": {\r\n ...applyFontWeightSemiBold(),\r\n ...applyMaxLines(3, getLineHeight(DialogArticleCardTypeRamp)),\r\n ...applyTypeRampConfig(DialogArticleCardTypeRamp)\r\n }\r\n },\r\n articleCard_headlineText: {\r\n \"padding-top\": \"3px\"\r\n },\r\n articleCard_headlineMask: {},\r\n articleCard_provider: {\r\n bottom: \"23px\",\r\n display: \"inline-flex\",\r\n position: \"absolute\",\r\n \"& $articleCard_providerImage\": {\r\n height: \"16px\"\r\n },\r\n \"& $articleCard_providerTitle\": {\r\n \"line-height\": \"16px\"\r\n }\r\n },\r\n articleCard_providerImage: {\r\n display: \"inline-block\",\r\n [applyLocalizedProperty(\"padding-right\", \"padding-left\", config.direction)]: \"8px\"\r\n },\r\n articleCard_providerTitle: {\r\n display: \"inline-block\",\r\n \"vertical-align\": \"top\",\r\n ...applyFontWeightNormal()\r\n },\r\n articleCard_noImage: {\r\n \"& $articleCard_textWrapper\": {\r\n height: \"auto\",\r\n \"text-align\": applyLocalizedProperty(\"left\", \"right\", config.direction)\r\n },\r\n \"& $articleCard_provider\": {\r\n \"margin-top\": \"15px\",\r\n position: \"static\"\r\n },\r\n \"& $articleCard_headlineText\": {\r\n \"padding-top\": \"0\"\r\n }\r\n }\r\n };\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n DialogArticleCard as BaseDialogArticleCard,\r\n DialogArticleCardHandledProps as BaseDialogArticleCardHandledProps,\r\n DialogArticleCardProps as BaseDialogArticleCardProps,\r\n DialogArticleCardManagedClasses,\r\n DialogArticleCardUnhandledProps\r\n} from \"./DialogArticleCard\";\r\nimport manageJss, { ManagedJSSProps } from \"@microsoft/fast-jss-manager-react\";\r\n\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { DialogArticleCardClassNameContract } from \"./DialogArticleCard.classnames\";\r\nimport { DialogArticleCardStyles } from \"./DialogArticleCard.styles\";\r\nimport { Subtract } from \"utility-types\";\r\n\r\n/*\r\n * The type returned by manageJss type is very complicated so we'll let the\r\n * compiler infer the type instead of re-declaring just for the package export\r\n */\r\n/* tslint:disable-next-line:typedef */\r\nconst DialogArticleCard = manageJss(DialogArticleCardStyles)(BaseDialogArticleCard);\r\ntype DialogArticleCard = InstanceType;\r\n\r\n// Create a valid JSS managed interface that doesn't require managed classes which are provided by the manageJSS HOC\r\ninterface DialogArticleCardHandledProps\r\n extends Subtract {}\r\n\r\n// Create type for manageJSS HOC styled instance we are exporting\r\ntype DialogArticleCardProps = ManagedJSSProps<\r\n BaseDialogArticleCardProps,\r\n DialogArticleCardClassNameContract,\r\n DesignSystem\r\n>;\r\n\r\nexport {\r\n DialogArticleCard,\r\n DialogArticleCardProps,\r\n DialogArticleCardHandledProps,\r\n DialogArticleCardUnhandledProps,\r\n DialogArticleCardManagedClasses,\r\n DialogArticleCardClassNameContract\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n SharingToolbarHandledProps as BaseComponentHandledProps,\r\n SharingToolbarProps as BaseComponentProps,\r\n ButtonItemType,\r\n ButtonType,\r\n SharingToolbarManagedClasses,\r\n SharingToolbarUnHandledProps\r\n} from \"./SharingToolbar.props\";\r\nimport manageJss, { ManagedJSSProps } from \"@microsoft/fast-jss-manager-react\";\r\n\r\nimport { SharingToolbar as BaseComponent } from \"./SharingToolbar\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { SharingToolbarClassNames } from \"./SharingToolbar.classnames\";\r\nimport { SharingToolbarStyles } from \"./SharingToolbar.styles\";\r\nimport { Subtract } from \"utility-types\";\r\n\r\n/*\r\n * The type returned by manageJss type is very complicated so we'll let the\r\n * compiler infer the type instead of re-declaring just for the package export\r\n */\r\n/* tslint:disable-next-line:typedef */\r\nconst SharingToolbar = manageJss(SharingToolbarStyles)(BaseComponent);\r\ntype SharingToolbar = InstanceType;\r\n\r\n// Create a valid JSS managed interface that doesn't require managed classes which are provided by the manageJSS HOC\r\ninterface SharingToolbarHandledProps extends Subtract { }\r\n\r\n// Create type for manageJSS HOC styled instance we are exporting\r\ntype SharingToolbarProps = ManagedJSSProps;\r\n\r\n// Export everything a user might need from this index file\r\nexport {\r\n ButtonType,\r\n ButtonItemType,\r\n SharingToolbar,\r\n SharingToolbarProps,\r\n SharingToolbarClassNames,\r\n SharingToolbarHandledProps,\r\n SharingToolbarUnHandledProps\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport * as ReactDOM from \"react-dom\";\r\n\r\nimport {\r\n ButtonItemType,\r\n ButtonType,\r\n SharingToolbarHandledProps,\r\n SharingToolbarProps,\r\n SharingToolbarUnHandledProps\r\n} from \"./SharingToolbar.props\";\r\nimport { Glyph, Icon } from \"@msnews/icon\";\r\nimport { SharingToolbarStyles, contextMenuStyles } from \"./SharingToolbar.styles\";\r\nimport { get, merge } from \"lodash-es\";\r\n\r\nimport { CardContextMenu } from \"@msnews/card-context-menu\";\r\nimport { ComponentStyles } from \"@microsoft/fast-jss-manager\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { DialogArticleCard } from \"../dialog-article-card\";\r\nimport { DialogClassNameContract } from \"@microsoft/fast-components-react-base\";\r\nimport Foundation from \"@microsoft/fast-components-foundation-react\";\r\nimport { HandledPropsKeys } from \"@msnews/core\";\r\nimport React from \"react\";\r\nimport { ShareDialog } from \"@msnews/share-dialog\";\r\nimport { SharingToolbarClassNames } from \".\";\r\nimport { SocialMediaIcon } from \"@msnews/social-media-icon\";\r\nimport { Status } from \"../../ContentActionsToolbar.constants\";\r\nimport { ToolbarPosition } from \"../../ContentActionsToolbar.props\";\r\nimport { moreOptionsMenuDefaultOffsetPos } from \"./SharingToolbar.constants\";\r\n\r\n/**\r\n * The local state interface of the component\r\n */\r\nexport interface SharingToolbarState {\r\n /** Flag to determine if share dialog should be displayed */\r\n shareDialogOpened: boolean\r\n}\r\n\r\n/**\r\n * Social media sharing toolbar component\r\n * @class - SharingToolbar\r\n * @classdesc - Sharing toolbar component class\r\n */\r\nexport class SharingToolbar extends Foundation {\r\n /**\r\n * Describes the object that enumerates all handled props for a component.\r\n * @protected\r\n * @type { HandledPropsKeys }\r\n */\r\n protected handledProps: HandledPropsKeys = {\r\n managedClasses: undefined,\r\n position: undefined,\r\n sharingButtons: undefined\r\n };\r\n\r\n /**\r\n * Stylesheet to apply to article card\r\n * @type {Partial>}\r\n */\r\n private articleCardStylesheet: Partial>;\r\n\r\n /**\r\n * Constructs a SharingToolbar component\r\n * @constructor\r\n * @param { SharingToolbarProps } props props contract\r\n */\r\n constructor(props: SharingToolbarProps) {\r\n super(props);\r\n this.state = {\r\n shareDialogOpened: false\r\n };\r\n }\r\n\r\n /**\r\n * Render sharing toolbar component\r\n * @public\r\n * @return {JSX.Element}\r\n */\r\n public render(): JSX.Element {\r\n return (\r\n
    \r\n
      \r\n {this.renderSharingButtons()}\r\n
    \r\n {this.renderShareDialog()}\r\n
    \r\n );\r\n }\r\n\r\n /**\r\n * Get the classname based on positioning of the toolbar\r\n */\r\n private getPositioningClassName(): string {\r\n const positionClass: string = this.props.position === ToolbarPosition.horizontal ?\r\n this.managedClass(\"iconListHorizontal\") :\r\n this.managedClass(\"iconListVertical\");\r\n\r\n return positionClass;\r\n }\r\n\r\n /**\r\n * Render the toolbar sharing buttons\r\n * @private\r\n * @return {JSX.Element} The sharing buttons element\r\n */\r\n private renderSharingButtons(): JSX.Element[] {\r\n if (!this.props.sharingButtons) {\r\n return ([]);\r\n }\r\n\r\n return this.props.sharingButtons.map(buttonItem => {\r\n if (!buttonItem.buttonData) {\r\n return null;\r\n }\r\n\r\n const buttonId: string = buttonItem.buttonType === ButtonType.SocialMedia ? buttonItem.buttonData.mediaType.toString() : buttonItem.buttonType.toString();\r\n let listItem: JSX.Element;\r\n\r\n switch (buttonItem.buttonType) {\r\n case ButtonType.SocialMedia:\r\n listItem = this.renderSocialMediaIcon(buttonItem);\r\n break;\r\n case ButtonType.ShareDialog:\r\n listItem = this.renderShareDialogIcon(buttonItem);\r\n break;\r\n case ButtonType.LikeDislike:\r\n listItem = this.renderLikeDislikeIcon(buttonItem);\r\n break;\r\n case ButtonType.MoreOptions:\r\n listItem = this.renderMoreOptionsIcon(buttonItem);\r\n break;\r\n default:\r\n return (null);\r\n }\r\n\r\n return (\r\n
  • \r\n {listItem}\r\n
  • \r\n );\r\n });\r\n }\r\n\r\n /**\r\n * Renders the share dialog\r\n * @private\r\n * @return {JSX.Element} The share dialog element\r\n */\r\n private renderShareDialog(): JSX.Element {\r\n const shareDialogItem = this.props.sharingButtons.find(x => x.buttonType === ButtonType.ShareDialog);\r\n if (!shareDialogItem || !shareDialogItem.buttonData) {\r\n return null;\r\n }\r\n\r\n const { shareDialogProps, dialogArticleCardProps, articleTelemetryTags } = shareDialogItem.buttonData;\r\n if (!this.state.shareDialogOpened || !shareDialogProps || !dialogArticleCardProps) {\r\n return null;\r\n }\r\n\r\n const shareDialog = (\r\n \r\n \r\n \r\n );\r\n\r\n return ReactDOM.createPortal(\r\n shareDialog,\r\n document.body\r\n );\r\n }\r\n\r\n /**\r\n * Renders the social media icon element\r\n * @private\r\n * @param {ButtonItemType} buttonItem The button item data\r\n * @return {JSX.Element} The share dialog element\r\n */\r\n private renderSocialMediaIcon(buttonItem: ButtonItemType): JSX.Element {\r\n const { attributes, mediaType, contentUrl, contentTitle, icon, ocid, target, newWindowTelemetryCall } = buttonItem.buttonData;\r\n if (!mediaType || !contentUrl || !contentTitle) {\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n );\r\n }\r\n\r\n /**\r\n * Renders the share dialog icon element\r\n * @private\r\n * @param {ButtonItemType} buttonItem The button item data\r\n * @return {JSX.Element} The share dialog icon element\r\n */\r\n private renderShareDialogIcon(buttonItem: ButtonItemType): JSX.Element {\r\n const { attributes, shareDialogProps, dialogArticleCardProps, onSelect } = buttonItem.buttonData;\r\n if (!shareDialogProps || !dialogArticleCardProps || !shareDialogProps.enabled || !shareDialogProps.contentTitle || !shareDialogProps.contentUrl) {\r\n return null;\r\n }\r\n\r\n return (\r\n this.onShareDialogOpen(event, onSelect)}\r\n {...attributes}\r\n {...buttonItem.telemetryTags}\r\n >\r\n \r\n \r\n);\r\n }\r\n\r\n /**\r\n * Renders the like/dislike icon element\r\n * @private\r\n * @param {ButtonItemType} buttonItem The button item data\r\n * @return {JSX.Element} The like/dislike icon element\r\n */\r\n private renderLikeDislikeIcon(buttonItem: ButtonItemType): JSX.Element {\r\n if (!buttonItem.buttonData.status) {\r\n return;\r\n }\r\n const { attributes, status, onSelect } = buttonItem.buttonData;\r\n\r\n const glyphType = status !== Status.DisLike ?\r\n (status === Status.Like ? Glyph.LikedText : Glyph.LikeText) :\r\n Glyph.DislikeText;\r\n\r\n const iconClassName = this.managedClass(\"icon_\" + status.toString() as keyof SharingToolbarClassNames);\r\n return (\r\n
    \r\n \r\n \r\n \r\n
    \r\n );\r\n }\r\n\r\n /**\r\n * Renders the more options icon element\r\n * @private\r\n * @param {ButtonItemType} buttonItem The button item data\r\n * @return {JSX.Element} The more options icon element\r\n */\r\n private renderMoreOptionsIcon(buttonItem: ButtonItemType): JSX.Element {\r\n if (!buttonItem.buttonData || !buttonItem.buttonData.status || !buttonItem.buttonData.menuItems) {\r\n return;\r\n }\r\n const { attributes, menuItems, offsetPos, zIndex } = buttonItem.buttonData;\r\n\r\n const positionOffset = this.props.position === ToolbarPosition.vertical\r\n ? { ...moreOptionsMenuDefaultOffsetPos, ...offsetPos }\r\n : undefined;\r\n\r\n return (\r\n \r\n \r\n
    \r\n );\r\n }\r\n\r\n /**\r\n * Enables and open the share dialog\r\n * @private\r\n * @param {any} event Event\r\n * @param {(e: any) => void)} onSelect Telemetry callback\r\n */\r\n private onShareDialogOpen = (event: any, onSelect: (e: any) => void): void => {\r\n this.setState({ shareDialogOpened: true });\r\n if (onSelect) {\r\n onSelect(event);\r\n }\r\n }\r\n\r\n /**\r\n * Disables and close the share dialog\r\n * @private\r\n */\r\n private onShareDialogClose = (): void => {\r\n this.setState({ shareDialogOpened: false });\r\n }\r\n\r\n /**\r\n * Utility function to simplify getting class name from managedClasses.\r\n * @param className - The class to get from managedClasses\r\n * @returns The managed class name\r\n */\r\n private managedClass(className: keyof SharingToolbarClassNames): string {\r\n return get(this.props.managedClasses, `${className}`);\r\n }\r\n}\r\n\r\nexport * from \"./SharingToolbar.props\";","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n ContentActionsToolbarHandledProps,\r\n ContentActionsToolbarUnhandledProps\r\n} from \"./ContentActionsToolbar.props\";\r\nimport { ContentActionsToolbarProps, ToolbarPosition } from \".\";\r\nimport { PlaceHolderId, experienceDefaultName } from \"./ContentActionsToolbar.constants\";\r\n\r\nimport { BaseExperience } from \"@msnews/experiences-base\";\r\nimport { ContentActionsToolbarAppErrors } from \"@msnews/diagnostics\";\r\nimport { HandledPropsKeys } from \"@msnews/core\";\r\nimport React from \"react\";\r\nimport { SharingToolbar } from \"./components/sharing-toolbar\";\r\nimport { TelemetryBase } from \"@msnews/core\";\r\nimport { classNames } from \"@microsoft/fast-web-utilities\";\r\nimport { markTtvr } from \"@msnews/diagnostics\";\r\n\r\n/**\r\n * Content Action toolbar base experience class\r\n * @class - ContentActionsToolbar\r\n * @classdesc - ContentActionsToolbar\r\n */\r\nexport class ContentActionsToolbar extends BaseExperience {\r\n /**\r\n * The ContentActionsToolbar default prop contract\r\n * Describes any default values for any component handled props\r\n * @public\r\n * @type { Partial }\r\n */\r\n public static defaultProps: Partial = {\r\n experienceName: experienceDefaultName\r\n };\r\n\r\n /**\r\n * The content action toolbar handled prop contract\r\n * Describes the object that enumerates all handled props for a component. This\r\n * object includes all props that can in some way consumed or manipulated by component\r\n * code.\r\n * @protected\r\n * @type { HandledPropsKeys }\r\n */\r\n protected handledProps: HandledPropsKeys = {\r\n contentStatus: undefined,\r\n customField: undefined,\r\n experienceName: undefined,\r\n managedClasses: undefined,\r\n onExperienceMilestoneTimingUpdate: undefined,\r\n position: undefined,\r\n rootTelemetryTags: undefined,\r\n sharingError: undefined,\r\n sharingToolbar: undefined,\r\n staticPosition: undefined\r\n };\r\n\r\n /**\r\n * Flag to confirm first render is completed\r\n * @type {boolean}\r\n */\r\n private firstRenderCompleted: boolean = false;\r\n\r\n /**\r\n * Constructs a ContentActionsToolbar component\r\n * @constructor\r\n * @param { ContentActionsToolbarProps } props props contract\r\n */\r\n constructor(props: ContentActionsToolbarProps) {\r\n super(props);\r\n }\r\n\r\n /**\r\n * Render App component.\r\n *\r\n * @public\r\n * @return {JSX.Element}\r\n */\r\n public render(): JSX.Element {\r\n super.render();\r\n\r\n if (this.props.position && this.props.sharingToolbar && this.props.sharingToolbar.sharingButtons && !this.props.sharingError) {\r\n return (\r\n
    \r\n \r\n
    \r\n );\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Trigger after component update\r\n */\r\n public componentDidUpdate(prevProps: ContentActionsToolbarHandledProps): void {\r\n super.componentDidUpdate(prevProps);\r\n\r\n if (!prevProps.staticPosition && this.shouldFlip()) {\r\n this.flipToolbar();\r\n }\r\n\r\n if (!this.firstRenderCompleted) {\r\n markTtvr(this.props.experienceName);\r\n this.firstRenderCompleted = true;\r\n }\r\n }\r\n\r\n /**\r\n * A handler that gets invoked for unhandled errors.\r\n * @param error error object.\r\n */\r\n public componentDidCatch(error: Error): void {\r\n const appError = { ...ContentActionsToolbarAppErrors.ContentActionsBaseExperienceError, message: `${error.message}\\n${error.stack}` };\r\n TelemetryBase.trackAppErrorEvent(appError);\r\n }\r\n\r\n /**\r\n * Get the classname based on positioning of the toolbar\r\n */\r\n private getPositioningClassName(): string {\r\n const managedClasses = this.props.managedClasses;\r\n const positionClass: string = this.props.position === ToolbarPosition.horizontal ?\r\n managedClasses.contentActionsToolbar_horizontal :\r\n managedClasses.contentActionsToolbar_vertical;\r\n\r\n return positionClass;\r\n }\r\n\r\n /**\r\n * Check if toolbar needs to flip from one position to another\r\n * @method\r\n * @returns {boolean} True if toolbar should flip. False otherwise.\r\n */\r\n private shouldFlip(): boolean {\r\n const { position } = this.props;\r\n\r\n const currentHostId = position === ToolbarPosition.vertical ? PlaceHolderId.vertical : PlaceHolderId.horizontal;\r\n const hostElem = document.getElementById(currentHostId);\r\n if (!hostElem) {\r\n TelemetryBase.trackAppErrorEvent({\r\n ...ContentActionsToolbarAppErrors.ContentActionsFlipToolbarError,\r\n message: \"Missing toolbar placeholder while checking shouldFlip\",\r\n pb: {\r\n ...ContentActionsToolbarAppErrors.ContentActionsFlipToolbarError.pb,\r\n customMessage: `CurrentHostId: ${currentHostId}`\r\n }\r\n });\r\n return false;\r\n }\r\n return hostElem.getElementsByTagName(\"ul\").length === 0;\r\n }\r\n\r\n /**\r\n * Move toolbar from one placeholder to another, depending on the toolbar position\r\n * @method\r\n */\r\n private flipToolbar(): void {\r\n const { position } = this.props;\r\n const prevHostId = position === ToolbarPosition.vertical ? PlaceHolderId.horizontal : PlaceHolderId.vertical;\r\n const newHostId = position === ToolbarPosition.vertical ? PlaceHolderId.vertical : PlaceHolderId.horizontal;\r\n\r\n const prevHostElem = document.getElementById(prevHostId);\r\n const newHostElem = document.getElementById(newHostId);\r\n\r\n if (!prevHostElem || !newHostElem) {\r\n return null;\r\n }\r\n\r\n while (prevHostElem.childNodes.length > 0) {\r\n newHostElem.appendChild(prevHostElem.childNodes[0]);\r\n }\r\n }\r\n}","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport { ComponentStyles } from \"@microsoft/fast-jss-manager\";\r\nimport { ContentActionsToolbarClassNames } from \".\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { toPx } from \"@microsoft/fast-jss-utilities\";\r\n\r\nconst toolbarMinDim = 40;\r\nconst iconHeight = 32;\r\n\r\n/**\r\n * The ContentActionsToolbar styles\r\n * @type {ComponentStyles}\r\n */\r\nexport const ContentActionsToolbarStyles: ComponentStyles = (config: DesignSystem) => {\r\n return {\r\n contentActionsToolbar: {\r\n \"background-color\": \"none\"\r\n },\r\n contentActionsToolbar_vertical: {\r\n width: toPx(toolbarMinDim)\r\n },\r\n contentActionsToolbar_horizontal: {\r\n width: \"auto\"\r\n }\r\n };\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport {\r\n ContentActionsToolbarHandledProps as BaseExperienceHandledProps,\r\n ContentActionsToolbarProps as BaseExperienceProps,\r\n ContentActionsToolbarManagedClasses,\r\n ContentActionsToolbarUnhandledProps,\r\n ToolbarPosition\r\n} from \"./ContentActionsToolbar.props\";\r\nimport {\r\n ContentActionsToolbarConfigSchema,\r\n ContentActionsToolbarMockConfig,\r\n ContentActionsToolbarMockState\r\n} from \"./experience-info\";\r\nimport { ContentActionsToolbarConnectorArgs, ContentActionsToolbarInspector } from \"./ContentActionsToolbar.inspector\";\r\nimport { PlaceHolderId, Status } from \"./ContentActionsToolbar.constants\";\r\nimport manageJss, { ManagedJSSProps } from \"@microsoft/fast-jss-manager-react\";\r\n\r\nimport {\r\n ContentActionsToolbar as BaseExperience\r\n} from \"./ContentActionsToolbar\";\r\nimport { ComponentClass } from \"react-redux\";\r\nimport { ContentActionsToolbarActions } from \"./ContentActionsToolbar.actions\";\r\nimport { ContentActionsToolbarClassNames } from \"./ContentActionsToolbar.classnames\";\r\nimport { ContentActionsToolbarConfig } from \"./ContentActionsToolbar.config\";\r\nimport { ContentActionsToolbarConnector } from \"./ContentActionsToolbar.connector\";\r\nimport { ContentActionsToolbarReducer } from \"./ContentActionsToolbar.reducer\";\r\nimport { ContentActionsToolbarState } from \"./ContentActionsToolbar.state\";\r\nimport { ContentActionsToolbarStyles } from \"./ContentActionsToolbar.styles\";\r\nimport { DesignSystem } from \"@microsoft/fast-components-styles-msft\";\r\nimport { ExperienceInfo } from \"@msnews/core\";\r\nimport { Subtract } from \"utility-types\";\r\n\r\n/*\r\n * The type returned by manageJss type is very complicated so we'll let the\r\n * compiler infer the type instead of re-declaring just for the package export\r\n */\r\n/* tslint:disable-next-line:typedef */\r\nconst ContentActionsToolbar = manageJss(ContentActionsToolbarStyles)(BaseExperience);\r\ntype ContentActionsToolbar = InstanceType;\r\n\r\n// Create a valid JSS managed interface that doesn't require managed classes which are provided by the manageJSS HOC\r\ninterface ContentActionsToolbarHandledProps extends Subtract {}\r\n\r\n// Create type for manageJSS HOC styled instance we are exporting\r\ntype ContentActionsToolbarProps = ManagedJSSProps;\r\n\r\nconst ToolingInfo: ExperienceInfo<\r\n ContentActionsToolbarConfig,\r\n ContentActionsToolbarState,\r\n ContentActionsToolbarProps,\r\n ContentActionsToolbarConnectorArgs\r\n> = {\r\n reactComponent: ContentActionsToolbar,\r\n experienceConfigSchema: ContentActionsToolbarConfigSchema,\r\n mockState: ContentActionsToolbarMockState,\r\n mockConfig: ContentActionsToolbarMockConfig,\r\n inspector: ContentActionsToolbarInspector.inspect\r\n};\r\n\r\n// type for ContentActionsToolbar experience to be invoked by other experiences\r\ntype ContentActionsToolbarExp = ComponentClass;\r\n\r\n// Export everything a user might need from this index file\r\nexport {\r\n ContentActionsToolbar,\r\n ContentActionsToolbarActions,\r\n ContentActionsToolbarConfig,\r\n ContentActionsToolbarConnector,\r\n ContentActionsToolbarExp,\r\n ContentActionsToolbarProps,\r\n ContentActionsToolbarReducer,\r\n ContentActionsToolbarState,\r\n ContentActionsToolbarClassNames,\r\n ContentActionsToolbarHandledProps,\r\n ContentActionsToolbarUnhandledProps,\r\n PlaceHolderId,\r\n Status,\r\n ToolbarPosition,\r\n ToolingInfo\r\n};","// © Microsoft Corporation. All rights reserved.\r\n\r\nimport \"../publicPath\";\r\n\r\nimport {\r\n ContentActionsToolbar,\r\n ContentActionsToolbarConfig,\r\n ContentActionsToolbarConnector,\r\n ContentActionsToolbarReducer,\r\n PlaceHolderId\r\n} from \"@msnews/content-actions-toolbar\";\r\nimport { ExperienceConfigWrapper, TelemetryBase, appEnvironment, resolver } from \"@msnews/core\";\r\nimport { ExperienceInitialProps, Telemetry } from \"@msnews/experiences-base\";\r\nimport { handleAppErrorEventCall, handlePartialPageImpressionCall, handleTelemetryCall } from \"../integration/PrimeTelemetry\";\r\n\r\nimport { ContentActionsToolbarAppErrors } from \"@msnews/diagnostics\";\r\nimport { DesignSystemDefaults } from \"@microsoft/fast-components-styles-msft\";\r\nimport { DesignSystemProvider } from \"@microsoft/fast-jss-manager-react\";\r\nimport { Mediator } from \"../integration/Mediator\";\r\nimport { PageBase } from \"@msnews/experiences-redux\";\r\nimport React from \"react\";\r\nimport { SharedDocumentType } from \"@msnews/views-helpers\";\r\nimport { ToolbarPosition } from \"@msnews/content-actions-toolbar\";\r\nimport { isNullOrUndefined } from \"util\";\r\n\r\n// export default function bootstrapPrimeHybrid(): void {\r\n// Get an instance of the PageBase for this app, and start the app\r\nconst app = PageBase.getInstance();\r\n\r\n// Mock documentId to be used when running hybrid locally for testing purposes\r\nconst mockDocumentId = \"BBKJJOS\";\r\n\r\n// Map base telemetry to prime library for hybrid\r\nTelemetryBase.trackAppErrorEvent = handleAppErrorEventCall;\r\nTelemetryBase.trackPartialImpression = handlePartialPageImpressionCall;\r\nTelemetryBase.trackEvent = handleTelemetryCall;\r\n\r\n// Start the App\r\napp.start();\r\n\r\nlet hostElement: HTMLElement;\r\n\r\nconst appTelemetry = Telemetry.createRootProps(\"spaContentActionsToolbarExperienceContainer\", undefined, appEnvironment.RootTelemetryId);\r\nconst initialProps: ExperienceInitialProps = {\r\n contentId: mockDocumentId,\r\n parentTelemetry: appTelemetry,\r\n context: {\r\n handleTelemetryCall: handleTelemetryCall\r\n }\r\n};\r\n\r\n/**\r\n * Otains document data properties from Prime placeholder and sets up the initial props and appEnv variables\r\n */\r\nfunction setupContentActionsInitialState(): void {\r\n // For Content Actions the placeholder can be in vertical in one prime region or horizontal in another prime region (depending on pagetype and column size)\r\n hostElement = document.getElementById(PlaceHolderId.vertical) || document.getElementById(PlaceHolderId.horizontal) || document.getElementById(\"content-actions-toolbar\");\r\n\r\n const dataset = hostElement.dataset || {};\r\n const cmsDocumentId: string = dataset.documentid || mockDocumentId;\r\n const isRSThree: string = dataset.isrsthree || \"false\";\r\n\r\n // Check for the existence of second position and sets staticsPosition accordingly\r\n var staticPosition = hostElement.id === PlaceHolderId.vertical ?\r\n document.getElementById(PlaceHolderId.horizontal) ? undefined : ToolbarPosition.vertical :\r\n document.getElementById(PlaceHolderId.vertical) ? undefined : ToolbarPosition.horizontal;\r\n\r\n // Set initital props\r\n initialProps.contentId = cmsDocumentId;\r\n initialProps.context.staticPosition = staticPosition;\r\n initialProps.context.isRSThree = (isRSThree.toLowerCase() === \"true\");\r\n initialProps.context.documentType = SharedDocumentType.CMS;\r\n\r\n // Update app environment\r\n appEnvironment.HostPage = {\r\n originalUrl: location.href,\r\n hostName: location.hostname,\r\n verticalKey: dataset.verticalkey || \"news\",\r\n categoryKey: dataset.categorykey || \"other\",\r\n topDomain: appEnvironment.HostPage.topDomain\r\n };\r\n}\r\n\r\n/**\r\n * Connected the component to the Redux store passing initial props data\r\n * @param {any} experienceConfig\r\n * @returns The Redux connected component\r\n */\r\nfunction connectContentActionsComponent(contentActionsToolbarConfig: ContentActionsToolbarConfig): Promise> {\r\n const contentActionsToolbarConnector = new ContentActionsToolbarConnector(\"ContentActionsToolbar\",\r\n \"\",\r\n app.rootReducer,\r\n new ContentActionsToolbarReducer(),\r\n app.store,\r\n contentActionsToolbarConfig);\r\n return contentActionsToolbarConnector.connectComponent(ContentActionsToolbar, initialProps);\r\n}\r\n\r\n/**\r\n * Render the experience on hostElement placeholder\r\n * @param contentActionsExperience\r\n */\r\nfunction renderExperience(contentActionsExperience: any): void {\r\n app.renderRootElement(\r\n React.createElement(\r\n DesignSystemProvider,\r\n { designSystem: DesignSystemDefaults },\r\n React.createElement(contentActionsExperience)\r\n ),\r\n hostElement\r\n );\r\n}\r\n\r\nlet contentActionsConfig: ContentActionsToolbarConfig;\r\nconst configFilePath = \"cms/api/amp/experienceConfigIndex/BBWebZe\";\r\nresolver.getConfig(configFilePath)\r\n .then((experienceConfig: ExperienceConfigWrapper) => {\r\n if (!experienceConfig) {\r\n throw Error(`Failed to load config file. Path: ${configFilePath}`);\r\n }\r\n contentActionsConfig = experienceConfig.properties;\r\n setupContentActionsInitialState();\r\n return connectContentActionsComponent(contentActionsConfig);\r\n }).then(renderExperience)\r\n .catch(error => {\r\n handleAppErrorEventCall({\r\n ...ContentActionsToolbarAppErrors.ContentActionsExperienceLoadError,\r\n message: `Error in hybrid loading Content Actions experience`,\r\n pb: {\r\n ...ContentActionsToolbarAppErrors.ContentActionsExperienceLoadError.pb,\r\n customMessage: `Url: ${location.href} Config: ${contentActionsConfig} Error: ${error}`\r\n }\r\n });\r\n return;\r\n }\r\n );\r\n\r\n// Listen to update events from Prime (Necessary as video page auto updates current displayed video)\r\nMediator.registerContentActionsUpdatedEvent(async () => {\r\n setupContentActionsInitialState();\r\n connectContentActionsComponent(contentActionsConfig)\r\n .then(renderExperience);\r\n});"],"sourceRoot":""}