{"version":3,"sources":["webpack:///./node_modules/moment/locale sync ^\\.\\/.*$?fe16","webpack:///./src/themes/columbiacrest/views/components/event-list-render.tsx?950f","webpack:///./src/themes/columbiacrest/views/event-list.view.tsx?96c2","webpack:///./src/Utilities/event-list-render.tsx?1a2e","webpack:///./src/modules/event-list/event-list.tsx?aafa","webpack:///./src/Utilities/product-placement-data-helper.ts?eab5"],"names":["map","webpackContext","req","id","webpackContextResolve","__webpack_require__","o","e","Error","code","keys","Object","resolve","module","exports","eventSortKey","event","startDate","format","time","name","oldSortKey","RenderEventList","React","render","this","_renderEventList","maxToDisplay","props","maximum","eventList","_formatList","events","_sortAndTrimList","length","noFutureEventsJSX","className","i","key","_renderEvent","href","pdp","src","productImage","alt","_renderDateRange","endDate","category","dangerouslySetInnerHTML","getRichTextHtml","intro","location","priceText","soldOut","soldOutText","isRange","isMonthSame","month","_renderDate","_renderMonth","_renderDay","date","_renderYear","list","fieldSources","default","entry","attributes","_getAttributes","debugMode","console","log","moment","tz","timezone","undefined","dates","_dateLogic","recordId","heading","price","productUrl","image","Introduction","description","Body","start","end","purchaseUrl","eventUrlTitle","downloadPDFUrl","reduce","output","attribute","Name","attributeSource","isSame","today","Date","now","startOf","filter","_isEventPast","sort","event1","event2","a","b","splice","isBefore","EventList","config","context","data","products","_getEventListItems","mapProductCollection","product","ProductDetails","result","_renderNoEventsMessage","resources","events__soldOut","request","query","debug","app","siteTimezone","noEventsText","textToShow","observer","returnedView","renderView","freePriceText","ratingAriaLabel","originalPriceText","currentPriceText","productItems","getProductUrlSync","actionContext","item","Description","mapProductPrice","ProductPrice","rating","mapProductRating","ProductRating","PrimaryImageUrl","RecordId","ProductAttributes","push","productPrice","requestContext","locale","currencyCode","CurrencyCode","currentPrice","_mapNumberToIPriceRange","CustomerContextualPrice","originalPrice","Math","max","BasePrice","TradeAgreementPrice","AdjustedPrice","productRating","ariaLabel","averageRating","AverageRating","totalRatings","TotalRatings","startingValue"],"mappings":"+EAAA,IAAIA,EAAM,CACT,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,QAAS,OACT,WAAY,OACZ,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,gBAAiB,OACjB,aAAc,OACd,gBAAiB,OACjB,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,UAAW,OACX,aAAc,OACd,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,WAAY,OACZ,cAAe,OACf,UAAW,OACX,aAAc,OACd,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,YAAa,OACb,eAAgB,OAChB,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,QAAS,OACT,WAAY,OACZ,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,UAAW,OACX,aAAc,OACd,QAAS,OACT,WAAY,OACZ,OAAQ,OACR,UAAW,OACX,QAAS,OACT,WAAY,OACZ,QAAS,OACT,aAAc,OACd,gBAAiB,OACjB,WAAY,OACZ,UAAW,OACX,aAAc,OACd,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,UAAW,OACX,OAAQ,OACR,YAAa,OACb,eAAgB,OAChB,UAAW,OACX,OAAQ,OACR,UAAW,OACX,aAAc,OACd,gBAAiB,OACjB,OAAQ,OACR,UAAW,OACX,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,OACd,UAAW,OACX,aAAc,QAIf,SAASC,EAAeC,GACvB,IAAIC,EAAKC,EAAsBF,GAC/B,OAAOG,EAAoBF,GAE5B,SAASC,EAAsBF,GAC9B,IAAIG,EAAoBC,EAAEN,EAAKE,GAAM,CACpC,IAAIK,EAAI,IAAIC,MAAM,uBAAyBN,EAAM,KAEjD,MADAK,EAAEE,KAAO,mBACHF,EAEP,OAAOP,EAAIE,GAEZD,EAAeS,KAAO,WACrB,OAAOC,OAAOD,KAAKV,IAEpBC,EAAeW,QAAUR,EACzBS,EAAOC,QAAUb,EACjBA,EAAeE,GAAK,Q,0ICnPpB,SAASY,EAAaC,GAGlB,MAAO,GAFcA,EAAMC,UAAWC,OAAO,QAE3BF,EAAMG,QAAQH,EAAMI,OAM1C,SAASC,EAAWL,GAChB,OAAQA,EAAMC,UAAWC,OAAO,KAStB,MAAOI,UAAwBC,gBAQlCC,SACH,OAAOC,KAAKC,mBAURA,mBACJ,MAAMC,EAAeF,KAAKG,MAAMC,SAAW,IAG3C,IAAIC,EAA+BL,KAAKM,YAAYN,KAAKG,MAAMI,QAO/D,OAJAF,EAAYL,KAAKQ,iBAAiBH,EAAWH,GAIpB,IAArBG,EAAUI,OACHT,KAAKG,MAAMO,kBAGdZ,uBAAKa,UAAU,cACVN,EAAU9B,IAAI,CAACgB,EAAwBqB,IACpCd,uBAAKe,IAAKtB,EAAMb,GAAIiC,UAAU,oBACzBC,EAAI,GAAKd,2BACTE,KAAKc,aAAavB,MAYnCuB,aAAavB,GACjB,OACIO,gBAACA,WAAc,KACXA,uBAAKa,UAAU,oBACXb,qBAAGa,UAAU,wBAAwBI,KAAMxB,EAAMyB,KAAKlB,uBAAKmB,IAAK1B,EAAM2B,aAAcC,IAAQ5B,EAAMI,KAAT,aAE7FG,uBAAKa,UAAU,sBACVX,KAAKoB,iBAAiB7B,EAAMC,UAAWD,EAAM8B,SAC9CvB,uBAAKa,UAAU,uBAAuBpB,EAAM+B,UAC5CxB,qBAAGa,UAAU,kBAAkBI,KAAMxB,EAAMyB,KAAMzB,EAAMI,MACvDG,uBAAKa,UAAU,mBAAmBY,wBAAyBC,0BAAgBjC,EAAMkC,SACjF3B,uBAAKa,UAAU,uBAAuBpB,EAAMmC,UAC5C5B,uBAAKa,UAAU,mBAAmBpB,EAAMG,MACxCI,uBAAKa,UAAU,oBAAoBpB,EAAMoC,WACzC7B,uBAAKa,UAAU,qBACXb,qBAAGa,UAAU,yBAAyBI,KAAMxB,EAAMyB,KAAG,YAQxDzB,EAAMqC,SAAW9B,uBAAKa,UAAU,uBAAuBX,KAAKG,MAAM0B,eAS3ET,iBAAiB5B,EAAsC6B,GAG3D,IAAK7B,IAAc6B,EACf,OAAO,KAIX,MAAMS,EAAWtC,GAAa6B,EACxBU,GAAevC,aAAA,EAAAA,EAAWwC,UAAUX,aAArB,EAAqBA,EAASW,OACnD,OACIlC,uBAAKa,UAAU,oBAGTmB,GACEhC,uBAAKa,UAAU,qBACVX,KAAKiC,YAAYzC,IAKzBsC,GAAWC,GACRjC,uBAAKa,UAAU,oBACVX,KAAKkC,aAAa1C,GACnBM,wBAAMa,UAAU,yBACZb,wBAAMa,UAAU,oBAAoBX,KAAKmC,WAAW3C,IACpDM,wBAAMa,UAAU,yBAFpB,IAGIb,wBAAMa,UAAU,kBAAkBX,KAAKmC,WAAWd,MAI7DS,IAAYC,GACTjC,uBAAKa,UAAU,oBACXb,wBAAMa,UAAU,oBAAoBX,KAAKiC,YAAYzC,IACrDM,wBAAMa,UAAU,yBAFpB,IAGIb,wBAAMa,UAAU,kBAAkBX,KAAKiC,YAAYZ,MAS/DY,YAAYG,GAChB,OACItC,gBAACA,WAAc,KACVE,KAAKkC,aAAaE,GAClBpC,KAAKmC,WAAWC,GAChBpC,KAAKqC,YAAYD,IAStBF,aAAaE,GACjB,OACItC,gBAACA,WAAc,KACXA,wBAAMa,UAAU,sBAAsByB,EAAK3C,OAAO,MAClDK,wBAAMa,UAAU,sBAAsByB,EAAK3C,OAAO,QAClDK,wBAAMa,UAAU,sBAAsByB,EAAK3C,OAAO,UAStD4C,YAAYD,GAChB,OACItC,gBAACA,WAAc,KACXA,wBAAMa,UAAU,qBAAqByB,EAAK3C,OAAO,OACjDK,wBAAMa,UAAU,qBAAqByB,EAAK3C,OAAO,UASrD0C,WAAWC,GACf,OACItC,gBAACA,WAAc,KACXA,wBAAMa,UAAU,kBAAkByB,EAAK3C,OAAO,OAYlDa,YAAYgC,GAEhB,MAAMC,EAAoC,CACtC,WAAY,sBACZ,aAAc,sBACd,kBAAmB,eACnB,WAAY,eAEZC,QAAS,aAGb,OAAOF,EAAK/D,IAAKkE,IAEb,MAAMC,EAAa1C,KAAK2C,eAAeF,EAAMC,WAAYH,GAErDvC,KAAKG,MAAMyC,WACXC,QAAQC,IAAI,mBAAoBJ,GAGpC,MAAMlD,EAAYkD,EAAW,cAAgBK,IAAOC,GAAGN,EAAW,cAAe1C,KAAKG,MAAM8C,eAAYC,EAClG7B,EAAUqB,EAAW,YAAcK,IAAOC,GAAGN,EAAW,YAAa1C,KAAKG,MAAM8C,eAAYC,EAC5FC,EAAQnD,KAAKoD,WAAW5D,EAAW6B,GACzC,MAAO,CACH3C,GAAI+D,EAAMY,SACV1D,KAAM8C,EAAMa,QACZC,MAAOd,EAAMc,MACbvC,IAAKyB,EAAMe,WACXtC,aAAcuB,EAAMgB,MAEpBnC,SAAUoB,EAAW,kBACrBjB,MAAOiB,EAAWgB,aAClBC,YAAajB,EAAWkB,KACxBpE,UAAW2D,EAAMU,MACjBxC,QAAS8B,EAAMW,IACfpE,KAAMgD,EAAW,cACjBhB,SAAUgB,EAAW,sBACrBf,UAAWe,EAAW,oBAEtBqB,YAAarB,EAAW,sBACxBsB,cAAetB,EAAW,mBAC1BuB,eAAgBvB,EAAW,oBAE3Bd,QAASc,EAAW,eAkBxBC,eAAeD,EAAsCH,GAEzD,OAAOG,EAAWwB,OAAO,CAACC,EAAQC,KAC9B,GAAIA,EAAUC,KAAM,CAChB,MAAMC,EAAkB/B,EAAa6B,EAAUC,OAAS9B,EAAaC,QACpE2B,EAAOC,EAAUC,MAAQD,EAAUE,GAGxC,OAAOH,GACR,IAUCf,WAAW5D,EAAsC6B,GAYrD,OAVIA,IAAY7B,IACZA,EAAY6B,EACZA,OAAU6B,GAIV1D,GAAaA,EAAU+E,OAAOlD,EAAS,SACvCA,OAAU6B,GAGP,CACHW,MAAOrE,EACPsE,IAAKzC,GAULb,iBAAiBH,EAA8BH,GAInD,MAAMsE,EAAQzB,IAAOC,GAAGyB,KAAKC,MAAO1E,KAAKG,MAAM8C,UAC1C0B,QAAQ,OAwCb,OArCAtE,EAAYA,EAAUuE,OAAQrF,KAGtBA,EAAMC,YAGEQ,KAAK6E,aAAatF,EAAOiF,KAQ3B/D,SACVJ,EAAYA,EAAUyE,KAAK,CAACC,EAAQC,KAChC,MAAMC,EAAIjF,KAAKG,MAAMyC,UAAYhD,EAAWmF,GAAUzF,EAAayF,GAC7DG,EAAIlF,KAAKG,MAAMyC,UAAYhD,EAAWoF,GAAU1F,EAAa0F,GAEnE,OAAIC,EAAIC,GACI,EACDD,EAAIC,EACJ,EAEA,KAMf7E,EAAUI,QACVP,GACCG,EAAUI,OAASP,GAEpBG,EAAU8E,OAAOjF,GAGdG,EAMHwE,aAAatF,EAAwB6C,GACzC,MAAM,UAAE5C,EAAF,QAAa6B,GAAY9B,EAI/B,OADqB8B,GAAW7B,GACZ4F,SAAShD,EAAM,QC/X3C,IAAMiD,EAAN,cAAwBvF,YAQbC,SACH,MAAM,OAAEuF,EAAF,QAAUC,EAAV,KAAmBC,GAASxF,KAAKG,MAEjCsF,EAA0BzF,KAAK0F,qBAErC,GAAID,GAAYA,EAAShF,OAAQ,CAC7B,MAAMJ,EAAYsF,YACdF,EAASb,OAAOgB,GAAWA,EAAQC,gBAAkBD,EAAQC,eAAexB,MAC5E,OACA,GACA,GACA,GACAkB,EACCC,EAAKlE,UAAYkE,EAAKlE,SAASwE,aAAW5C,GAG/C,GAAI7C,GAAkC,IAArBA,EAAUI,OACvB,OACIX,gBAACD,EAAe,CACZU,OAAQF,EACRD,QAASkF,EAAOpF,aAChBQ,kBAAmBV,KAAK+F,yBACxBlE,YAAa7B,KAAKG,MAAM6F,UAAUC,gBAClCrD,UAAW5C,KAAKG,MAAMoF,QAAQW,QAAQC,SAAWnG,KAAKG,MAAMoF,QAAQW,QAAQC,MAAMC,MAClFnD,SAAUjD,KAAKG,MAAMkG,IAAIf,OAAOgB,cAAgB,wBAIxDzD,QAAQC,IAAI,0EAGpB,OAAO9C,KAAK+F,yBAWRA,yBACJ,MAAM,aAAEQ,GAAiBvG,KAAKG,MAAMmF,OAE9BkB,EAAaD,GAAgB,YAEnC,OAEIzG,uBACIa,UAAU,mBACVY,wBAAyBC,0BAAgBgF,KAY7Cd,qBACJ,MAAM,KAAEF,GAASxF,KAAKG,MACtB,IAAIsF,EAA0B,GAc9B,OAJID,EAAKC,UAAYD,EAAKC,SAASK,QAAUN,EAAKC,SAASK,OAAOrF,OAAS,IACvEgF,EAAWD,EAAKC,SAASK,QAGtBL,IAvFTJ,EAAS,sBADdoB,KACKpB,GA2FSA,a,0ICpEf,SAAS/F,EAAaC,GAGlB,MAAO,GAFcA,EAAMC,UAAWC,OAAO,QAE3BF,EAAMG,QAAQH,EAAMI,OAM1C,SAASC,EAAWL,GAChB,OAAQA,EAAMC,UAAWC,OAAO,KAStB,MAAOI,UAAwBC,gBAQlCC,SACH,OAAOC,KAAKC,mBAURA,mBACJ,MAAMC,EAAeF,KAAKG,MAAMC,SAAW,IAG3C,IAAIC,EAA+BL,KAAKM,YAAYN,KAAKG,MAAMI,QAO/D,OAJAF,EAAYL,KAAKQ,iBAAiBH,EAAWH,GAIpB,IAArBG,EAAUI,OACHT,KAAKG,MAAMO,kBAGdZ,uBAAKa,UAAU,cACVN,EAAU9B,IAAKgB,GACZO,uBAAKe,IAAKtB,EAAMb,GAAIiC,UAAU,oBACzBX,KAAKc,aAAavB,MAYnCuB,aAAavB,GACjB,OACIO,gBAACA,WAAc,KACXA,uBAAKa,UAAU,oBACXb,qBAAGa,UAAU,wBAAwBI,KAAMxB,EAAMyB,KAAKlB,uBAAKmB,IAAK1B,EAAM2B,aAAcC,IAAQ5B,EAAMI,KAAT,aAE7FG,uBAAKa,UAAU,sBACVX,KAAKoB,iBAAiB7B,EAAMC,UAAWD,EAAM8B,SAC9CvB,uBAAKa,UAAU,uBAAuBpB,EAAM+B,UAC5CxB,qBAAGa,UAAU,kBAAkBI,KAAMxB,EAAMyB,KAAMzB,EAAMI,MACvDG,uBAAKa,UAAU,mBAAmBY,wBAAyBC,0BAAgBjC,EAAMkC,SACjF3B,uBAAKa,UAAU,uBAAuBpB,EAAMmC,UAC5C5B,uBAAKa,UAAU,mBAAmBpB,EAAMG,MACxCI,uBAAKa,UAAU,oBAAoBpB,EAAMoC,WACzC7B,uBAAKa,UAAU,qBACXb,qBAAGa,UAAU,yBAAyBI,KAAMxB,EAAMyB,KAAG,YAQxDzB,EAAMqC,SAAW9B,uBAAKa,UAAU,uBAAuBX,KAAKG,MAAM0B,eAS3ET,iBAAiB5B,EAAsC6B,GAG3D,IAAK7B,IAAc6B,EACf,OAAO,KAIX,MAAMS,EAAWtC,GAAa6B,EAE9B,OACIvB,uBAAKa,UAAU,oBAGTmB,GACEhC,uBAAKa,UAAU,qBACVX,KAAKiC,YAAYzC,IAKzBsC,GACGhC,uBAAKa,UAAU,oBACXb,wBAAMa,UAAU,oBAAoBX,KAAKiC,YAAYzC,IACrDM,wBAAMa,UAAU,yBAFpB,IAGIb,wBAAMa,UAAU,kBAAkBX,KAAKiC,YAAYZ,MAS/DY,YAAYG,GAChB,OACItC,gBAACA,WAAc,KACVE,KAAKkC,aAAaE,GAClBpC,KAAKmC,WAAWC,GAChBpC,KAAKqC,YAAYD,IAStBF,aAAaE,GACjB,OACItC,gBAACA,WAAc,KACXA,wBAAMa,UAAU,sBAAsByB,EAAK3C,OAAO,MAClDK,wBAAMa,UAAU,sBAAsByB,EAAK3C,OAAO,QAClDK,wBAAMa,UAAU,sBAAsByB,EAAK3C,OAAO,UAStD4C,YAAYD,GAChB,OACItC,gBAACA,WAAc,KACXA,wBAAMa,UAAU,qBAAqByB,EAAK3C,OAAO,OACjDK,wBAAMa,UAAU,qBAAqByB,EAAK3C,OAAO,UASrD0C,WAAWC,GACf,OACItC,gBAACA,WAAc,KACXA,wBAAMa,UAAU,kBAAkByB,EAAK3C,OAAO,OAYlDa,YAAYgC,GAEhB,MAAMC,EAAoC,CACtC,WAAY,sBACZ,aAAc,sBACd,kBAAmB,eACnB,WAAY,eAEZC,QAAS,aAGb,OAAOF,EAAK/D,IAAKkE,IAEb,MAAMC,EAAa1C,KAAK2C,eAAeF,EAAMC,WAAYH,GAErDvC,KAAKG,MAAMyC,WACXC,QAAQC,IAAI,mBAAoBJ,GAGpC,MAAMlD,EAAYkD,EAAW,cAAgBK,IAAOC,GAAGN,EAAW,cAAe1C,KAAKG,MAAM8C,eAAYC,EAClG7B,EAAUqB,EAAW,YAAcK,IAAOC,GAAGN,EAAW,YAAa1C,KAAKG,MAAM8C,eAAYC,EAC5FC,EAAQnD,KAAKoD,WAAW5D,EAAW6B,GACzC,MAAO,CACH3C,GAAI+D,EAAMY,SACV1D,KAAM8C,EAAMa,QACZC,MAAOd,EAAMc,MACbvC,IAAKyB,EAAMe,WACXtC,aAAcuB,EAAMgB,MAEpBnC,SAAUoB,EAAW,kBACrBjB,MAAOiB,EAAWgB,aAClBC,YAAajB,EAAWkB,KACxBpE,UAAW2D,EAAMU,MACjBxC,QAAS8B,EAAMW,IACfpE,KAAMgD,EAAW,cACjBhB,SAAUgB,EAAW,sBACrBf,UAAWe,EAAW,oBAEtBqB,YAAarB,EAAW,sBACxBsB,cAAetB,EAAW,mBAC1BuB,eAAgBvB,EAAW,oBAE3Bd,QAASc,EAAW,eAkBxBC,eAAeD,EAAsCH,GAEzD,OAAOG,EAAWwB,OAAO,CAACC,EAAQC,KAC9B,GAAIA,EAAUC,KAAM,CAChB,MAAMC,EAAkB/B,EAAa6B,EAAUC,OAAS9B,EAAaC,QACpE2B,EAAOC,EAAUC,MAAQD,EAAUE,GAGxC,OAAOH,GACR,IAUCf,WAAW5D,EAAsC6B,GAYrD,OAVIA,IAAY7B,IACZA,EAAY6B,EACZA,OAAU6B,GAIV1D,GAAaA,EAAU+E,OAAOlD,EAAS,SACvCA,OAAU6B,GAGP,CACHW,MAAOrE,EACPsE,IAAKzC,GAULb,iBAAiBH,EAA8BH,GAInD,MAAMsE,EAAQzB,IAAOC,GAAGyB,KAAKC,MAAO1E,KAAKG,MAAM8C,UAC1C0B,QAAQ,OAwCb,OArCAtE,EAAYA,EAAUuE,OAAQrF,KAGtBA,EAAMC,YAGEQ,KAAK6E,aAAatF,EAAOiF,KAQ3B/D,SACVJ,EAAYA,EAAUyE,KAAK,CAACC,EAAQC,KAChC,MAAMC,EAAIjF,KAAKG,MAAMyC,UAAYhD,EAAWmF,GAAUzF,EAAayF,GAC7DG,EAAIlF,KAAKG,MAAMyC,UAAYhD,EAAWoF,GAAU1F,EAAa0F,GAEnE,OAAIC,EAAIC,GACI,EACDD,EAAIC,EACJ,EAEA,KAMf7E,EAAUI,QACVP,GACCG,EAAUI,OAASP,GAEpBG,EAAU8E,OAAOjF,GAGdG,EAMHwE,aAAatF,EAAwB6C,GACzC,MAAM,UAAE5C,EAAF,QAAa6B,GAAY9B,EAI/B,OADqB8B,GAAW7B,GACZ4F,SAAShD,EAAM,QCpX3C,IAAMiD,EAAN,cAAwBvF,YAQbC,SACH,MAAM,OAAEuF,EAAF,QAAUC,EAAV,KAAmBC,GAASxF,KAAKG,MACjCuG,EAAe1G,KAAKG,MAAMwG,WAAW3G,KAAKG,OAChD,GAAGuG,EACC,OAAOA,EAGX,MAAMjB,EAA0BzF,KAAK0F,qBAErC,GAAID,GAAYA,EAAShF,OAAQ,CAC7B,MAAMJ,EAAYsF,YACdF,EAASb,OAAOgB,GAAWA,EAAQC,gBAAkBD,EAAQC,eAAexB,MAC5E,OACA,GACA,GACA,GACAkB,EACCC,EAAKlE,UAAYkE,EAAKlE,SAASwE,aAAW5C,GAG/C,GAAI7C,GAAkC,IAArBA,EAAUI,OACvB,OACIX,gBAACD,EAAe,CACZU,OAAQF,EACRD,QAASkF,EAAOpF,aAChBQ,kBAAmBV,KAAK+F,yBACxBlE,YAAa7B,KAAKG,MAAM6F,UAAUC,gBAClCrD,UAAW5C,KAAKG,MAAMoF,QAAQW,QAAQC,SAAWnG,KAAKG,MAAMoF,QAAQW,QAAQC,MAAMC,MAClFnD,SAAUjD,KAAKG,MAAMkG,IAAIf,OAAOgB,cAAgB,wBAIxDzD,QAAQC,IAAI,0EAGpB,OAAO9C,KAAK+F,yBAWRA,yBACJ,MAAM,aAAEQ,GAAiBvG,KAAKG,MAAMmF,OAE9BkB,EAAaD,GAAgB,YAEnC,OAEIzG,uBACIa,UAAU,mBACVY,wBAAyBC,0BAAgBgF,KAY7Cd,qBACJ,MAAM,KAAEF,GAASxF,KAAKG,MACtB,IAAIsF,EAA0B,GAc9B,OAJID,EAAKC,UAAYD,EAAKC,SAASK,QAAUN,EAAKC,SAASK,OAAOrF,OAAS,IACvEgF,EAAWD,EAAKC,SAASK,QAGtBL,IA3FTJ,EAAS,sBADdoB,KACKpB,GA+FSA,a,kCCxHf,kDA4FM,SAAUM,EACZF,EACAmB,EACAC,EACAC,EACAC,EACAxB,EACAjE,GAEA,IAAImE,GAAgC,IAApBA,EAAShF,OACrB,MAAO,GAGX,MAAMuG,EAA4C,GAmBlD,OAlBAvB,EAASlH,IAAIqH,IACT,GAAGA,GAAWA,EAAQC,eAAgB,CACtC,MAAMrC,EAAayD,4BAAkBrB,EAAQC,eAAgBN,GAAWA,EAAQ2B,cAAe5F,GACzF6F,EAAO,CACT7D,QAASsC,EAAQC,eAAexB,KAChCV,YAAaiC,EAAQC,eAAeuB,YACpC7D,MAAO8D,EAAgBzB,EAAQ0B,aAAc/B,EAAQW,QAASU,EAAeE,EAAmBC,GAChGQ,OAAQC,EAAiB5B,EAAQ6B,cAAeZ,GAChDpD,MAAOmC,EAAQC,eAAe6B,gBAC9BlE,WAAYA,EACZH,SAAUuC,EAAQC,eAAe8B,SAEjCjF,WAAYkD,EAAQgC,mBAExBZ,EAAaa,KAAKV,MAIfH,EAGX,SAASK,EACLS,EACAC,EACAnB,EACAE,EACAC,GAEA,GAAIe,GAAgBC,EAChB,MAAO,CACHC,OAAQD,EAAeC,OACvBC,aAAcH,EAAaI,aAAeJ,EAAaI,aAAe,GACtEtB,cAAeA,EACfE,kBAAmBA,EACnBC,iBAAkBA,EAClBoB,aAAcC,EAAwBN,EAAaO,yBACnDC,cAAeF,EACXG,KAAKC,IAAIV,EAAaW,WAAa,EAAGX,EAAaY,qBAAuB,EAAGZ,EAAaa,eAAiB,KAsB3H,SAASnB,EACLoB,EACAC,GAEA,GAAID,EACA,MAAO,CACHE,cAAeF,EAAcG,eAAiB,EAC9CC,aAAcJ,EAAcK,cAAgB,EAC5CJ,UAAWA,GAMvB,SAAST,EAAwB7E,GAC7B,QAAcL,IAAVK,EACA,MAAO,CACH2F,cAAe3F","file":"static/js/27.4691f4cbc90683e38e98.chunk.js","sourcesContent":["var map = {\n\t\"./af\": \"K/tc\",\n\t\"./af.js\": \"K/tc\",\n\t\"./ar\": \"jnO4\",\n\t\"./ar-dz\": \"o1bE\",\n\t\"./ar-dz.js\": \"o1bE\",\n\t\"./ar-kw\": \"Qj4J\",\n\t\"./ar-kw.js\": \"Qj4J\",\n\t\"./ar-ly\": \"HP3h\",\n\t\"./ar-ly.js\": \"HP3h\",\n\t\"./ar-ma\": \"CoRJ\",\n\t\"./ar-ma.js\": \"CoRJ\",\n\t\"./ar-sa\": \"gjCT\",\n\t\"./ar-sa.js\": \"gjCT\",\n\t\"./ar-tn\": \"bYM6\",\n\t\"./ar-tn.js\": \"bYM6\",\n\t\"./ar.js\": \"jnO4\",\n\t\"./az\": \"SFxW\",\n\t\"./az.js\": \"SFxW\",\n\t\"./be\": \"H8ED\",\n\t\"./be.js\": \"H8ED\",\n\t\"./bg\": \"hKrs\",\n\t\"./bg.js\": \"hKrs\",\n\t\"./bm\": \"p/rL\",\n\t\"./bm.js\": \"p/rL\",\n\t\"./bn\": \"kEOa\",\n\t\"./bn-bd\": \"loYQ\",\n\t\"./bn-bd.js\": \"loYQ\",\n\t\"./bn.js\": \"kEOa\",\n\t\"./bo\": \"0mo+\",\n\t\"./bo.js\": \"0mo+\",\n\t\"./br\": \"aIdf\",\n\t\"./br.js\": \"aIdf\",\n\t\"./bs\": \"JVSJ\",\n\t\"./bs.js\": \"JVSJ\",\n\t\"./ca\": \"1xZ4\",\n\t\"./ca.js\": \"1xZ4\",\n\t\"./cs\": \"PA2r\",\n\t\"./cs.js\": \"PA2r\",\n\t\"./cv\": \"A+xa\",\n\t\"./cv.js\": \"A+xa\",\n\t\"./cy\": \"l5ep\",\n\t\"./cy.js\": \"l5ep\",\n\t\"./da\": \"DxQv\",\n\t\"./da.js\": \"DxQv\",\n\t\"./de\": \"tGlX\",\n\t\"./de-at\": \"s+uk\",\n\t\"./de-at.js\": \"s+uk\",\n\t\"./de-ch\": \"u3GI\",\n\t\"./de-ch.js\": \"u3GI\",\n\t\"./de.js\": \"tGlX\",\n\t\"./dv\": \"WYrj\",\n\t\"./dv.js\": \"WYrj\",\n\t\"./el\": \"jUeY\",\n\t\"./el.js\": \"jUeY\",\n\t\"./en-au\": \"Dmvi\",\n\t\"./en-au.js\": \"Dmvi\",\n\t\"./en-ca\": \"OIYi\",\n\t\"./en-ca.js\": \"OIYi\",\n\t\"./en-gb\": \"Oaa7\",\n\t\"./en-gb.js\": \"Oaa7\",\n\t\"./en-ie\": \"4dOw\",\n\t\"./en-ie.js\": \"4dOw\",\n\t\"./en-il\": \"czMo\",\n\t\"./en-il.js\": \"czMo\",\n\t\"./en-in\": \"7C5Q\",\n\t\"./en-in.js\": \"7C5Q\",\n\t\"./en-nz\": \"b1Dy\",\n\t\"./en-nz.js\": \"b1Dy\",\n\t\"./en-sg\": \"t+mt\",\n\t\"./en-sg.js\": \"t+mt\",\n\t\"./eo\": \"Zduo\",\n\t\"./eo.js\": \"Zduo\",\n\t\"./es\": \"iYuL\",\n\t\"./es-do\": \"CjzT\",\n\t\"./es-do.js\": \"CjzT\",\n\t\"./es-mx\": \"tbfe\",\n\t\"./es-mx.js\": \"tbfe\",\n\t\"./es-us\": \"Vclq\",\n\t\"./es-us.js\": \"Vclq\",\n\t\"./es.js\": \"iYuL\",\n\t\"./et\": \"7BjC\",\n\t\"./et.js\": \"7BjC\",\n\t\"./eu\": \"D/JM\",\n\t\"./eu.js\": \"D/JM\",\n\t\"./fa\": \"jfSC\",\n\t\"./fa.js\": \"jfSC\",\n\t\"./fi\": \"gekB\",\n\t\"./fi.js\": \"gekB\",\n\t\"./fil\": \"1ppg\",\n\t\"./fil.js\": \"1ppg\",\n\t\"./fo\": \"ByF4\",\n\t\"./fo.js\": \"ByF4\",\n\t\"./fr\": \"nyYc\",\n\t\"./fr-ca\": \"2fjn\",\n\t\"./fr-ca.js\": \"2fjn\",\n\t\"./fr-ch\": \"Dkky\",\n\t\"./fr-ch.js\": \"Dkky\",\n\t\"./fr.js\": \"nyYc\",\n\t\"./fy\": \"cRix\",\n\t\"./fy.js\": \"cRix\",\n\t\"./ga\": \"USCx\",\n\t\"./ga.js\": \"USCx\",\n\t\"./gd\": \"9rRi\",\n\t\"./gd.js\": \"9rRi\",\n\t\"./gl\": \"iEDd\",\n\t\"./gl.js\": \"iEDd\",\n\t\"./gom-deva\": \"qvJo\",\n\t\"./gom-deva.js\": \"qvJo\",\n\t\"./gom-latn\": \"DKr+\",\n\t\"./gom-latn.js\": \"DKr+\",\n\t\"./gu\": \"4MV3\",\n\t\"./gu.js\": \"4MV3\",\n\t\"./he\": \"x6pH\",\n\t\"./he.js\": \"x6pH\",\n\t\"./hi\": \"3E1r\",\n\t\"./hi.js\": \"3E1r\",\n\t\"./hr\": \"S6ln\",\n\t\"./hr.js\": \"S6ln\",\n\t\"./hu\": \"WxRl\",\n\t\"./hu.js\": \"WxRl\",\n\t\"./hy-am\": \"1rYy\",\n\t\"./hy-am.js\": \"1rYy\",\n\t\"./id\": \"UDhR\",\n\t\"./id.js\": \"UDhR\",\n\t\"./is\": \"BVg3\",\n\t\"./is.js\": \"BVg3\",\n\t\"./it\": \"bpih\",\n\t\"./it-ch\": \"bxKX\",\n\t\"./it-ch.js\": \"bxKX\",\n\t\"./it.js\": \"bpih\",\n\t\"./ja\": \"B55N\",\n\t\"./ja.js\": \"B55N\",\n\t\"./jv\": \"tUCv\",\n\t\"./jv.js\": \"tUCv\",\n\t\"./ka\": \"IBtZ\",\n\t\"./ka.js\": \"IBtZ\",\n\t\"./kk\": \"bXm7\",\n\t\"./kk.js\": \"bXm7\",\n\t\"./km\": \"6B0Y\",\n\t\"./km.js\": \"6B0Y\",\n\t\"./kn\": \"PpIw\",\n\t\"./kn.js\": \"PpIw\",\n\t\"./ko\": \"Ivi+\",\n\t\"./ko.js\": \"Ivi+\",\n\t\"./ku\": \"JCF/\",\n\t\"./ku.js\": \"JCF/\",\n\t\"./ky\": \"lgnt\",\n\t\"./ky.js\": \"lgnt\",\n\t\"./lb\": \"RAwQ\",\n\t\"./lb.js\": \"RAwQ\",\n\t\"./lo\": \"sp3z\",\n\t\"./lo.js\": \"sp3z\",\n\t\"./lt\": \"JvlW\",\n\t\"./lt.js\": \"JvlW\",\n\t\"./lv\": \"uXwI\",\n\t\"./lv.js\": \"uXwI\",\n\t\"./me\": \"KTz0\",\n\t\"./me.js\": \"KTz0\",\n\t\"./mi\": \"aIsn\",\n\t\"./mi.js\": \"aIsn\",\n\t\"./mk\": \"aQkU\",\n\t\"./mk.js\": \"aQkU\",\n\t\"./ml\": \"AvvY\",\n\t\"./ml.js\": \"AvvY\",\n\t\"./mn\": \"lYtQ\",\n\t\"./mn.js\": \"lYtQ\",\n\t\"./mr\": \"Ob0Z\",\n\t\"./mr.js\": \"Ob0Z\",\n\t\"./ms\": \"6+QB\",\n\t\"./ms-my\": \"ZAMP\",\n\t\"./ms-my.js\": \"ZAMP\",\n\t\"./ms.js\": \"6+QB\",\n\t\"./mt\": \"G0Uy\",\n\t\"./mt.js\": \"G0Uy\",\n\t\"./my\": \"honF\",\n\t\"./my.js\": \"honF\",\n\t\"./nb\": \"bOMt\",\n\t\"./nb.js\": \"bOMt\",\n\t\"./ne\": \"OjkT\",\n\t\"./ne.js\": \"OjkT\",\n\t\"./nl\": \"+s0g\",\n\t\"./nl-be\": \"2ykv\",\n\t\"./nl-be.js\": \"2ykv\",\n\t\"./nl.js\": \"+s0g\",\n\t\"./nn\": \"uEye\",\n\t\"./nn.js\": \"uEye\",\n\t\"./oc-lnc\": \"Fnuy\",\n\t\"./oc-lnc.js\": \"Fnuy\",\n\t\"./pa-in\": \"8/+R\",\n\t\"./pa-in.js\": \"8/+R\",\n\t\"./pl\": \"jVdC\",\n\t\"./pl.js\": \"jVdC\",\n\t\"./pt\": \"8mBD\",\n\t\"./pt-br\": \"0tRk\",\n\t\"./pt-br.js\": \"0tRk\",\n\t\"./pt.js\": \"8mBD\",\n\t\"./ro\": \"lyxo\",\n\t\"./ro.js\": \"lyxo\",\n\t\"./ru\": \"lXzo\",\n\t\"./ru.js\": \"lXzo\",\n\t\"./sd\": \"Z4QM\",\n\t\"./sd.js\": \"Z4QM\",\n\t\"./se\": \"//9w\",\n\t\"./se.js\": \"//9w\",\n\t\"./si\": \"7aV9\",\n\t\"./si.js\": \"7aV9\",\n\t\"./sk\": \"e+ae\",\n\t\"./sk.js\": \"e+ae\",\n\t\"./sl\": \"gVVK\",\n\t\"./sl.js\": \"gVVK\",\n\t\"./sq\": \"yPMs\",\n\t\"./sq.js\": \"yPMs\",\n\t\"./sr\": \"zx6S\",\n\t\"./sr-cyrl\": \"E+lV\",\n\t\"./sr-cyrl.js\": \"E+lV\",\n\t\"./sr.js\": \"zx6S\",\n\t\"./ss\": \"Ur1D\",\n\t\"./ss.js\": \"Ur1D\",\n\t\"./sv\": \"X709\",\n\t\"./sv.js\": \"X709\",\n\t\"./sw\": \"dNwA\",\n\t\"./sw.js\": \"dNwA\",\n\t\"./ta\": \"PeUW\",\n\t\"./ta.js\": \"PeUW\",\n\t\"./te\": \"XLvN\",\n\t\"./te.js\": \"XLvN\",\n\t\"./tet\": \"V2x9\",\n\t\"./tet.js\": \"V2x9\",\n\t\"./tg\": \"Oxv6\",\n\t\"./tg.js\": \"Oxv6\",\n\t\"./th\": \"EOgW\",\n\t\"./th.js\": \"EOgW\",\n\t\"./tk\": \"Wv91\",\n\t\"./tk.js\": \"Wv91\",\n\t\"./tl-ph\": \"Dzi0\",\n\t\"./tl-ph.js\": \"Dzi0\",\n\t\"./tlh\": \"z3Vd\",\n\t\"./tlh.js\": \"z3Vd\",\n\t\"./tr\": \"DoHr\",\n\t\"./tr.js\": \"DoHr\",\n\t\"./tzl\": \"z1FC\",\n\t\"./tzl.js\": \"z1FC\",\n\t\"./tzm\": \"wQk9\",\n\t\"./tzm-latn\": \"tT3J\",\n\t\"./tzm-latn.js\": \"tT3J\",\n\t\"./tzm.js\": \"wQk9\",\n\t\"./ug-cn\": \"YRex\",\n\t\"./ug-cn.js\": \"YRex\",\n\t\"./uk\": \"raLr\",\n\t\"./uk.js\": \"raLr\",\n\t\"./ur\": \"UpQW\",\n\t\"./ur.js\": \"UpQW\",\n\t\"./uz\": \"Loxo\",\n\t\"./uz-latn\": \"AQ68\",\n\t\"./uz-latn.js\": \"AQ68\",\n\t\"./uz.js\": \"Loxo\",\n\t\"./vi\": \"KSF8\",\n\t\"./vi.js\": \"KSF8\",\n\t\"./x-pseudo\": \"/X5v\",\n\t\"./x-pseudo.js\": \"/X5v\",\n\t\"./yo\": \"fzPg\",\n\t\"./yo.js\": \"fzPg\",\n\t\"./zh-cn\": \"XDpg\",\n\t\"./zh-cn.js\": \"XDpg\",\n\t\"./zh-hk\": \"SatO\",\n\t\"./zh-hk.js\": \"SatO\",\n\t\"./zh-mo\": \"OmwH\",\n\t\"./zh-mo.js\": \"OmwH\",\n\t\"./zh-tw\": \"kOpN\",\n\t\"./zh-tw.js\": \"kOpN\"\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"RnhZ\";","// ============================================================================\r\n// Renders a list of events\r\n// ============================================================================\r\nimport { getRichTextHtml, IDictionary } from '@msdyn365-commerce/core';\r\nimport moment from 'moment-timezone';\r\nimport * as React from 'react';\r\nimport { IProductAttributeProps } from '../../../../Utilities/product-lightbox';\r\nimport { IPrice, IProductPlacementDataItem } from '../../../../Utilities/product-placement-data-helper';\r\n\r\n// ============================================================================\r\n// INTERFACES AND CONSTANTS\r\n// ============================================================================\r\n\r\nexport interface IEventListRenderProps {\r\n events: IProductPlacementDataItem[];\r\n maximum?: number;\r\n noFutureEventsJSX: JSX.Element;\r\n timezone: string;\r\n soldOutText?: string;\r\n debugMode?: boolean;\r\n}\r\n\r\ntype maybeMoment = moment.Moment | undefined;\r\n\r\n// Internal interface for info on a single event\r\ninterface IFormattedEvent {\r\n id?: number;\r\n name?: string;\r\n description?: string;\r\n price?: IPrice;\r\n pdp?: string;\r\n category?: string;\r\n intro?: string;\r\n startDate?: maybeMoment;\r\n endDate?: maybeMoment;\r\n time?: string;\r\n location?: string;\r\n priceText?: string;\r\n purchaseUrl?: string;\r\n eventUrlTitle?: string;\r\n soldOut?: boolean;\r\n downloadPDFUrl?: string;\r\n productImage?: string;\r\n}\r\n\r\n// -------------------------------------------------------------\r\n// Hides errors by attempting to prevent ambigious values\r\n// -------------------------------------------------------------\r\nfunction eventSortKey(event: IFormattedEvent): string {\r\n const date: string = event.startDate!.format('X');\r\n\r\n return `${date}-${event.time}-${event.name}`;\r\n}\r\n\r\n// -------------------------------------------------------------\r\n// OLD, ambiguous method. Produces errors in some cases.\r\n// -------------------------------------------------------------\r\nfunction oldSortKey(event: IFormattedEvent): number {\r\n return +event.startDate!.format('X');\r\n}\r\n\r\n// =============================================================================\r\n// CLASS DEFINITION\r\n// =============================================================================\r\n/**\r\n * Event list render component\r\n */\r\nexport default class RenderEventList extends React.PureComponent {\r\n\r\n // ============================================================================\r\n // PUBLIC METHODS\r\n // ============================================================================\r\n\r\n // -------------------------------------------------------------\r\n // -------------------------------------------------------------\r\n public render(): JSX.Element | null {\r\n return this._renderEventList();\r\n }\r\n\r\n // ============================================================================\r\n // JSX FRAGMENTS\r\n // ============================================================================\r\n\r\n // -------------------------------------------------------------\r\n // Render the event list\r\n // -------------------------------------------------------------\r\n private _renderEventList(): JSX.Element {\r\n const maxToDisplay = this.props.maximum || 999; // Default to a large number, but not ludicrously large\r\n\r\n // Format the event list\r\n let eventList: IFormattedEvent[] = this._formatList(this.props.events);\r\n\r\n // Clean up the list before display\r\n eventList = this._sortAndTrimList(eventList, maxToDisplay);\r\n\r\n // If the event list still has something to display after being trimmed\r\n // then show the list or display the no current events jsx message\r\n if (eventList.length === 0) {\r\n return this.props.noFutureEventsJSX;\r\n } else {\r\n return (\r\n
\r\n {eventList.map((event: IFormattedEvent, i: number) => (\r\n
\r\n {i > 0 &&
}\r\n {this._renderEvent(event)}\r\n
\r\n ))}\r\n
\r\n );\r\n }\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Render a single event\r\n // -------------------------------------------------------------\r\n // tslint:disable: react-no-dangerous-html\r\n private _renderEvent(event: IFormattedEvent): JSX.Element | null {\r\n return (\r\n \r\n
\r\n {`${event.name}\r\n
\r\n
\r\n {this._renderDateRange(event.startDate, event.endDate)}\r\n
{event.category}
\r\n {event.name}\r\n
\r\n
{event.location}
\r\n
{event.time}
\r\n
{event.priceText}
\r\n
\r\n Details\r\n
\r\n {/*
\r\n {event.eventUrlTitle}\r\n
\r\n
\r\n Download PDF\r\n
*/}\r\n {event.soldOut &&
{this.props.soldOutText}
}\r\n
\r\n \r\n );\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Render a single event\r\n // -------------------------------------------------------------\r\n private _renderDateRange(startDate: moment.Moment | undefined, endDate: moment.Moment | undefined): JSX.Element | null {\r\n\r\n // Early out if there's no dates\r\n if (!startDate && !endDate) {\r\n return null;\r\n }\r\n\r\n // Both: Display as range\r\n const isRange = (startDate && endDate);\r\n const isMonthSame = (startDate?.month === endDate?.month);\r\n return (\r\n
\r\n\r\n {/* Single Date */}\r\n {!isRange &&\r\n
\r\n {this._renderDate(startDate!)}\r\n
\r\n }\r\n\r\n {/* Date Range */}\r\n {isRange && isMonthSame &&\r\n
\r\n {this._renderMonth(startDate!)}\r\n \r\n {this._renderDay(startDate!)}\r\n {/* No content: fill in with css */}\r\n {this._renderDay(endDate!)}\r\n \r\n
\r\n }\r\n {isRange && !isMonthSame &&\r\n
\r\n {this._renderDate(startDate!)}\r\n {/* No content: fill in with css */}\r\n {this._renderDate(endDate!)}\r\n
\r\n }\r\n
\r\n );\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // -------------------------------------------------------------\r\n private _renderDate(date: moment.Moment): JSX.Element {\r\n return (\r\n \r\n {this._renderMonth(date)}\r\n {this._renderDay(date)}\r\n {this._renderYear(date)}\r\n \r\n );\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Render a month in several different formats.\r\n // It's up to the css to hide unwanted versions.\r\n // -------------------------------------------------------------\r\n private _renderMonth(date: moment.Moment): JSX.Element {\r\n return (\r\n \r\n {date.format('M')}\r\n {date.format('MMM')}\r\n {date.format('MMMM')}\r\n \r\n );\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Render a year in several different formats.\r\n // It's up to the css to hide unwanted versions.\r\n // -------------------------------------------------------------\r\n private _renderYear(date: moment.Moment): JSX.Element {\r\n return (\r\n \r\n {date.format('YY')}\r\n {date.format('YYYY')}\r\n \r\n );\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Render a day in several different formats (Currently only one).\r\n // It's up to the css to hide unwanted versions.\r\n // -------------------------------------------------------------\r\n private _renderDay(date: moment.Moment): JSX.Element {\r\n return (\r\n \r\n {date.format('D')}\r\n \r\n );\r\n }\r\n\r\n // ============================================================================\r\n // PRIVATE METHODS\r\n // ============================================================================\r\n\r\n // -------------------------------------------------------------\r\n // Formats the product and attribute data into a more useful format\r\n // -------------------------------------------------------------\r\n private _formatList(list: IProductPlacementDataItem[]): IFormattedEvent[] {\r\n\r\n const fieldSources: IDictionary = {\r\n 'End Date': 'DateTimeOffsetValue',\r\n 'Start Date': 'DateTimeOffsetValue',\r\n 'Can add to cart': 'BooleanValue', // Boolean DataTypeValue: 6\r\n 'Sold Out': 'BooleanValue',\r\n\r\n default: 'TextValue'\r\n };\r\n\r\n return list.map((entry) => {\r\n // @ts-ignore\r\n const attributes = this._getAttributes(entry.attributes, fieldSources);\r\n\r\n if (this.props.debugMode) {\r\n console.log('Event Attributes', attributes);\r\n }\r\n\r\n const startDate = attributes['Start Date'] ? moment.tz(attributes['Start Date'], this.props.timezone) : undefined;\r\n const endDate = attributes['End Date'] ? moment.tz(attributes['End Date'], this.props.timezone) : undefined;\r\n const dates = this._dateLogic(startDate, endDate);\r\n return {\r\n id: entry.recordId,\r\n name: entry.heading,\r\n price: entry.price,\r\n pdp: entry.productUrl,\r\n productImage: entry.image,\r\n\r\n category: attributes['SLR Event Type'],\r\n intro: attributes.Introduction,\r\n description: attributes.Body, // PDP only\r\n startDate: dates.start,\r\n endDate: dates.end,\r\n time: attributes['Time Range'],\r\n location: attributes['SLR Event Location'],\r\n priceText: attributes['Event Price Info'],\r\n\r\n purchaseUrl: attributes['Event Purchase URL'],\r\n eventUrlTitle: attributes['Event URL Title'],\r\n downloadPDFUrl: attributes['Download PDF URL'],\r\n\r\n soldOut: attributes['Sold Out']\r\n };\r\n });\r\n\r\n /* OTHER ATTRIBUTES\r\n Event purchase\r\n Event Purchase URL\r\n Event URL Title\r\n Featured Y/N\r\n Video Caption\r\n Video Title\r\n */\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Converts the attribute list into a simple hash\r\n // -------------------------------------------------------------\r\n // tslint:disable-next-line:no-any\r\n private _getAttributes(attributes: IProductAttributeProps[], fieldSources: IDictionary): IDictionary {\r\n\r\n return attributes.reduce((output, attribute) => {\r\n if (attribute.Name) {\r\n const attributeSource = fieldSources[attribute.Name] || fieldSources.default;\r\n (output[attribute.Name] = attribute[attributeSource]);\r\n }\r\n\r\n return output;\r\n }, {}); // <--- I hate the `align` rule\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Date logic:\r\n // Only start date: Good\r\n // Only end date: Move to start date\r\n // Start and end are the same: Remove end date\r\n // Both: Display as range\r\n // -------------------------------------------------------------\r\n private _dateLogic(startDate: moment.Moment | undefined, endDate: moment.Moment | undefined): { start: maybeMoment; end: maybeMoment } {\r\n // Only end date: Move to start date\r\n if (endDate && !startDate) {\r\n startDate = endDate;\r\n endDate = undefined;\r\n }\r\n\r\n // Start and end are the same: Remove end date\r\n if (startDate && startDate.isSame(endDate, 'day')) {\r\n endDate = undefined;\r\n }\r\n\r\n return {\r\n start: startDate,\r\n end: endDate\r\n };\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Sort the list by date, then trim it.\r\n //\r\n // @FIXME/dg: These should ideally be handled by the server query\r\n // to minimize request size\r\n // -------------------------------------------------------------\r\n private _sortAndTrimList(eventList: IFormattedEvent[], maxToDisplay: number): IFormattedEvent[] {\r\n\r\n // subtracting 1 from the current date so that we are able to show events\r\n // on the day of; since we are using the isBefore method.\r\n const today = moment.tz(Date.now(), this.props.timezone)\r\n .startOf('day');\r\n\r\n // Filter out events with no dates (logic has already occurred)\r\n eventList = eventList.filter((event: IFormattedEvent) => {\r\n\r\n // ensure events have a starting date at least, end date is unreliable\r\n if (event.startDate) {\r\n\r\n // Remove events that have past\r\n return !this._isEventPast(event, today);\r\n }\r\n\r\n return false;\r\n });\r\n\r\n // Sort the list by date\r\n // @FIXME/dg: Band-aid version. Messy! Move to its own function if we keep this.\r\n if (eventList.length) {\r\n eventList = eventList.sort((event1, event2) => {\r\n const a = this.props.debugMode ? oldSortKey(event1) : eventSortKey(event1);\r\n const b = this.props.debugMode ? oldSortKey(event2) : eventSortKey(event2);\r\n\r\n if (a < b) {\r\n return -1;\r\n } else if (a > b) {\r\n return 1;\r\n } else {\r\n return 0;\r\n }\r\n });\r\n }\r\n\r\n // Trim unwanted events\r\n if (eventList.length &&\r\n maxToDisplay &&\r\n (eventList.length > maxToDisplay)\r\n ) {\r\n eventList.splice(maxToDisplay);\r\n }\r\n\r\n return eventList;\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Determine if an event is passed the day given\r\n // -------------------------------------------------------------\r\n private _isEventPast(event: IFormattedEvent, date: moment.Moment): boolean {\r\n const { startDate, endDate } = event;\r\n\r\n // we want to use the date the references the events closure the closest\r\n const furthestDate = endDate || startDate!;\r\n return furthestDate.isBefore(date, 'day');\r\n }\r\n}\r\n","/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License. See License.txt in the project root for license information.\r\n *--------------------------------------------------------------------------------------------*/\r\n\r\nimport { observer } from 'mobx-react';\r\nimport * as React from 'react';\r\n\r\nimport { FullProduct } from '@msdyn365-commerce/commerce-entities';\r\nimport { getRichTextHtml } from '@msdyn365-commerce/core';\r\nimport { mapProductCollection } from '../../../Utilities/product-placement-data-helper';\r\nimport { IEventListData } from '../../../modules/event-list/event-list.data';\r\nimport { IEventListProps } from '../../../modules/event-list/event-list.props.autogenerated';\r\n\r\nimport RenderEventList from './components/event-list-render';\r\n\r\n// ==============================================================================\r\n// CLASS DEFINITION\r\n// ==============================================================================\r\n/**\r\n *\r\n * EventList component\r\n * @extends {React.Component>}\r\n */\r\n@observer\r\nclass EventList extends React.Component> {\r\n\r\n // =============================================================================\r\n // PUBLIC METHODS\r\n // =============================================================================\r\n\r\n // --------------------------------------------------------------\r\n // --------------------------------------------------------------\r\n public render(): JSX.Element {\r\n const { config, context, data } = this.props;\r\n\r\n const products: FullProduct[] = this._getEventListItems();\r\n\r\n if (products && products.length) {\r\n const eventList = mapProductCollection(\r\n products.filter(product => product.ProductDetails && product.ProductDetails.Name),\r\n 'Free',\r\n '',\r\n '',\r\n '',\r\n context,\r\n (data.category && data.category.result) || undefined\r\n );\r\n\r\n if (eventList && eventList.length !== 0) {\r\n return (\r\n \r\n );\r\n } else {\r\n console.log('Could not map product collection to product placement item succesfully');\r\n }\r\n }\r\n return this._renderNoEventsMessage();\r\n }\r\n\r\n // =============================================================================\r\n // JSX FRAGMENTS\r\n // =============================================================================\r\n\r\n // --------------------------------------------------------------\r\n // If no events are present, render this instead of the events\r\n // list\r\n // --------------------------------------------------------------\r\n private _renderNoEventsMessage(): JSX.Element {\r\n const { noEventsText } = this.props.config;\r\n\r\n const textToShow = noEventsText || 'No Events';\r\n\r\n return (\r\n // tslint:disable-next-line: react-no-dangerous-html\r\n \r\n );\r\n }\r\n\r\n // =============================================================================\r\n // PRIVATE METHODS\r\n // =============================================================================\r\n\r\n // --------------------------------------------------------------\r\n // Construct the event list data\r\n // --------------------------------------------------------------\r\n private _getEventListItems(): FullProduct[] {\r\n const { data } = this.props;\r\n let products: FullProduct[] = [];\r\n\r\n // TODO: May need to add refineSearch in future.\r\n // const refineSearchProducts = this.props.data.refineSearchProducts && this.props.data.refineSearchProducts.result;\r\n // if (refineSearchProducts && refineSearchProducts.refinementCriteria && refineSearchProducts.refinementCriteria.length) {\r\n // if (refineSearchProducts.productSearchResult && refineSearchProducts.productSearchResult.length) {\r\n // products = refineSearchProducts.productSearchResult;\r\n // }\r\n // }\r\n\r\n if (data.products && data.products.result && data.products.result.length > 0) {\r\n products = data.products.result;\r\n }\r\n\r\n return products;\r\n }\r\n}\r\n\r\nexport default EventList;","// ============================================================================\r\n// Renders a list of events\r\n// ============================================================================\r\nimport { getRichTextHtml, IDictionary } from '@msdyn365-commerce/core';\r\nimport moment from 'moment-timezone';\r\nimport * as React from 'react';\r\nimport { IProductAttributeProps } from './product-lightbox';\r\nimport { IPrice, IProductPlacementDataItem } from './product-placement-data-helper';\r\n\r\n// ============================================================================\r\n// INTERFACES AND CONSTANTS\r\n// ============================================================================\r\n\r\nexport interface IEventListRenderProps {\r\n events: IProductPlacementDataItem[];\r\n maximum?: number;\r\n noFutureEventsJSX: JSX.Element;\r\n timezone: string;\r\n soldOutText?: string;\r\n debugMode?: boolean;\r\n}\r\n\r\ntype maybeMoment = moment.Moment | undefined;\r\n\r\n// Internal interface for info on a single event\r\ninterface IFormattedEvent {\r\n id?: number;\r\n name?: string;\r\n description?: string;\r\n price?: IPrice;\r\n pdp?: string;\r\n category?: string;\r\n intro?: string;\r\n startDate?: maybeMoment;\r\n endDate?: maybeMoment;\r\n time?: string;\r\n location?: string;\r\n priceText?: string;\r\n purchaseUrl?: string;\r\n eventUrlTitle?: string;\r\n soldOut?: boolean;\r\n downloadPDFUrl?: string;\r\n productImage?: string;\r\n}\r\n\r\n// -------------------------------------------------------------\r\n// Hides errors by attempting to prevent ambigious values\r\n// -------------------------------------------------------------\r\nfunction eventSortKey(event: IFormattedEvent): string {\r\n const date: string = event.startDate!.format('X');\r\n\r\n return `${date}-${event.time}-${event.name}`;\r\n}\r\n\r\n// -------------------------------------------------------------\r\n// OLD, ambiguous method. Produces errors in some cases.\r\n// -------------------------------------------------------------\r\nfunction oldSortKey(event: IFormattedEvent): number {\r\n return +event.startDate!.format('X');\r\n}\r\n\r\n// =============================================================================\r\n// CLASS DEFINITION\r\n// =============================================================================\r\n/**\r\n * Event list render component\r\n */\r\nexport default class RenderEventList extends React.PureComponent {\r\n\r\n // ============================================================================\r\n // PUBLIC METHODS\r\n // ============================================================================\r\n\r\n // -------------------------------------------------------------\r\n // -------------------------------------------------------------\r\n public render(): JSX.Element | null {\r\n return this._renderEventList();\r\n }\r\n\r\n // ============================================================================\r\n // JSX FRAGMENTS\r\n // ============================================================================\r\n\r\n // -------------------------------------------------------------\r\n // Render the event list\r\n // -------------------------------------------------------------\r\n private _renderEventList(): JSX.Element {\r\n const maxToDisplay = this.props.maximum || 999; // Default to a large number, but not ludicrously large\r\n\r\n // Format the event list\r\n let eventList: IFormattedEvent[] = this._formatList(this.props.events);\r\n\r\n // Clean up the list before display\r\n eventList = this._sortAndTrimList(eventList, maxToDisplay);\r\n\r\n // If the event list still has something to display after being trimmed\r\n // then show the list or display the no current events jsx message\r\n if (eventList.length === 0) {\r\n return this.props.noFutureEventsJSX;\r\n } else {\r\n return (\r\n
\r\n {eventList.map((event: IFormattedEvent) => (\r\n
\r\n {this._renderEvent(event)}\r\n
\r\n ))}\r\n
\r\n );\r\n }\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Render a single event\r\n // -------------------------------------------------------------\r\n // tslint:disable: react-no-dangerous-html\r\n private _renderEvent(event: IFormattedEvent): JSX.Element | null {\r\n return (\r\n \r\n
\r\n {`${event.name}\r\n
\r\n
\r\n {this._renderDateRange(event.startDate, event.endDate)}\r\n
{event.category}
\r\n {event.name}\r\n
\r\n
{event.location}
\r\n
{event.time}
\r\n
{event.priceText}
\r\n
\r\n Details\r\n
\r\n {/* \r\n
\r\n Download PDF\r\n
*/}\r\n {event.soldOut &&
{this.props.soldOutText}
}\r\n
\r\n \r\n );\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Render a single event\r\n // -------------------------------------------------------------\r\n private _renderDateRange(startDate: moment.Moment | undefined, endDate: moment.Moment | undefined): JSX.Element | null {\r\n\r\n // Early out if there's no dates\r\n if (!startDate && !endDate) {\r\n return null;\r\n }\r\n\r\n // Both: Display as range\r\n const isRange = (startDate && endDate);\r\n\r\n return (\r\n
\r\n\r\n {/* Single Date */}\r\n {!isRange &&\r\n
\r\n {this._renderDate(startDate!)}\r\n
\r\n }\r\n\r\n {/* Date Range */}\r\n {isRange &&\r\n
\r\n {this._renderDate(startDate!)}\r\n {/* No content: fill in with css */}\r\n {this._renderDate(endDate!)}\r\n
\r\n }\r\n
\r\n );\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // -------------------------------------------------------------\r\n private _renderDate(date: moment.Moment): JSX.Element {\r\n return (\r\n \r\n {this._renderMonth(date)}\r\n {this._renderDay(date)}\r\n {this._renderYear(date)}\r\n \r\n );\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Render a month in several different formats.\r\n // It's up to the css to hide unwanted versions.\r\n // -------------------------------------------------------------\r\n private _renderMonth(date: moment.Moment): JSX.Element {\r\n return (\r\n \r\n {date.format('M')}\r\n {date.format('MMM')}\r\n {date.format('MMMM')}\r\n \r\n );\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Render a year in several different formats.\r\n // It's up to the css to hide unwanted versions.\r\n // -------------------------------------------------------------\r\n private _renderYear(date: moment.Moment): JSX.Element {\r\n return (\r\n \r\n {date.format('YY')}\r\n {date.format('YYYY')}\r\n \r\n );\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Render a day in several different formats (Currently only one).\r\n // It's up to the css to hide unwanted versions.\r\n // -------------------------------------------------------------\r\n private _renderDay(date: moment.Moment): JSX.Element {\r\n return (\r\n \r\n {date.format('D')}\r\n \r\n );\r\n }\r\n\r\n // ============================================================================\r\n // PRIVATE METHODS\r\n // ============================================================================\r\n\r\n // -------------------------------------------------------------\r\n // Formats the product and attribute data into a more useful format\r\n // -------------------------------------------------------------\r\n private _formatList(list: IProductPlacementDataItem[]): IFormattedEvent[] {\r\n\r\n const fieldSources: IDictionary = {\r\n 'End Date': 'DateTimeOffsetValue',\r\n 'Start Date': 'DateTimeOffsetValue',\r\n 'Can add to cart': 'BooleanValue', // Boolean DataTypeValue: 6\r\n 'Sold Out': 'BooleanValue',\r\n\r\n default: 'TextValue'\r\n };\r\n\r\n return list.map((entry) => {\r\n // @ts-ignore\r\n const attributes = this._getAttributes(entry.attributes, fieldSources);\r\n\r\n if (this.props.debugMode) {\r\n console.log('Event Attributes', attributes);\r\n }\r\n\r\n const startDate = attributes['Start Date'] ? moment.tz(attributes['Start Date'], this.props.timezone) : undefined;\r\n const endDate = attributes['End Date'] ? moment.tz(attributes['End Date'], this.props.timezone) : undefined;\r\n const dates = this._dateLogic(startDate, endDate);\r\n return {\r\n id: entry.recordId,\r\n name: entry.heading,\r\n price: entry.price,\r\n pdp: entry.productUrl,\r\n productImage: entry.image,\r\n\r\n category: attributes['SLR Event Type'],\r\n intro: attributes.Introduction,\r\n description: attributes.Body, // PDP only\r\n startDate: dates.start,\r\n endDate: dates.end,\r\n time: attributes['Time Range'],\r\n location: attributes['SLR Event Location'],\r\n priceText: attributes['Event Price Info'],\r\n\r\n purchaseUrl: attributes['Event Purchase URL'],\r\n eventUrlTitle: attributes['Event URL Title'],\r\n downloadPDFUrl: attributes['Download PDF URL'],\r\n\r\n soldOut: attributes['Sold Out']\r\n };\r\n });\r\n\r\n /* OTHER ATTRIBUTES\r\n Event purchase\r\n Event Purchase URL\r\n Event URL Title\r\n Featured Y/N\r\n Video Caption\r\n Video Title\r\n */\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Converts the attribute list into a simple hash\r\n // -------------------------------------------------------------\r\n // tslint:disable-next-line:no-any\r\n private _getAttributes(attributes: IProductAttributeProps[], fieldSources: IDictionary): IDictionary {\r\n\r\n return attributes.reduce((output, attribute) => {\r\n if (attribute.Name) {\r\n const attributeSource = fieldSources[attribute.Name] || fieldSources.default;\r\n (output[attribute.Name] = attribute[attributeSource]);\r\n }\r\n\r\n return output;\r\n }, {}); // <--- I hate the `align` rule\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Date logic:\r\n // Only start date: Good\r\n // Only end date: Move to start date\r\n // Start and end are the same: Remove end date\r\n // Both: Display as range\r\n // -------------------------------------------------------------\r\n private _dateLogic(startDate: moment.Moment | undefined, endDate: moment.Moment | undefined): { start: maybeMoment; end: maybeMoment } {\r\n // Only end date: Move to start date\r\n if (endDate && !startDate) {\r\n startDate = endDate;\r\n endDate = undefined;\r\n }\r\n\r\n // Start and end are the same: Remove end date\r\n if (startDate && startDate.isSame(endDate, 'day')) {\r\n endDate = undefined;\r\n }\r\n\r\n return {\r\n start: startDate,\r\n end: endDate\r\n };\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Sort the list by date, then trim it.\r\n //\r\n // @FIXME/dg: These should ideally be handled by the server query\r\n // to minimize request size\r\n // -------------------------------------------------------------\r\n private _sortAndTrimList(eventList: IFormattedEvent[], maxToDisplay: number): IFormattedEvent[] {\r\n\r\n // subtracting 1 from the current date so that we are able to show events\r\n // on the day of; since we are using the isBefore method.\r\n const today = moment.tz(Date.now(), this.props.timezone)\r\n .startOf('day');\r\n\r\n // Filter out events with no dates (logic has already occurred)\r\n eventList = eventList.filter((event: IFormattedEvent) => {\r\n\r\n // ensure events have a starting date at least, end date is unreliable\r\n if (event.startDate) {\r\n\r\n // Remove events that have past\r\n return !this._isEventPast(event, today);\r\n }\r\n\r\n return false;\r\n });\r\n\r\n // Sort the list by date\r\n // @FIXME/dg: Band-aid version. Messy! Move to its own function if we keep this.\r\n if (eventList.length) {\r\n eventList = eventList.sort((event1, event2) => {\r\n const a = this.props.debugMode ? oldSortKey(event1) : eventSortKey(event1);\r\n const b = this.props.debugMode ? oldSortKey(event2) : eventSortKey(event2);\r\n\r\n if (a < b) {\r\n return -1;\r\n } else if (a > b) {\r\n return 1;\r\n } else {\r\n return 0;\r\n }\r\n });\r\n }\r\n\r\n // Trim unwanted events\r\n if (eventList.length &&\r\n maxToDisplay &&\r\n (eventList.length > maxToDisplay)\r\n ) {\r\n eventList.splice(maxToDisplay);\r\n }\r\n\r\n return eventList;\r\n }\r\n\r\n // -------------------------------------------------------------\r\n // Determine if an event is passed the day given\r\n // -------------------------------------------------------------\r\n private _isEventPast(event: IFormattedEvent, date: moment.Moment): boolean {\r\n const { startDate, endDate } = event;\r\n\r\n // we want to use the date the references the events closure the closest\r\n const furthestDate = endDate || startDate!;\r\n return furthestDate.isBefore(date, 'day');\r\n }\r\n}\r\n","/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License. See License.txt in the project root for license information.\r\n *--------------------------------------------------------------------------------------------*/\r\n\r\nimport { observer } from 'mobx-react';\r\nimport * as React from 'react';\r\n\r\nimport { FullProduct } from '@msdyn365-commerce/commerce-entities';\r\nimport { getRichTextHtml } from '@msdyn365-commerce/core';\r\nimport { mapProductCollection } from '../../Utilities/product-placement-data-helper';\r\nimport { IEventListData } from './event-list.data';\r\nimport { IEventListProps } from './event-list.props.autogenerated';\r\n\r\nimport RenderEventList from '../../Utilities/event-list-render';\r\n\r\n// ==============================================================================\r\n// CLASS DEFINITION\r\n// ==============================================================================\r\n/**\r\n *\r\n * EventList component\r\n * @extends {React.Component>}\r\n */\r\n@observer\r\nclass EventList extends React.Component> {\r\n\r\n // =============================================================================\r\n // PUBLIC METHODS\r\n // =============================================================================\r\n\r\n // --------------------------------------------------------------\r\n // --------------------------------------------------------------\r\n public render(): JSX.Element {\r\n const { config, context, data } = this.props;\r\n const returnedView = this.props.renderView(this.props);\r\n if(returnedView){\r\n return returnedView;\r\n }\r\n\r\n const products: FullProduct[] = this._getEventListItems();\r\n\r\n if (products && products.length) {\r\n const eventList = mapProductCollection(\r\n products.filter(product => product.ProductDetails && product.ProductDetails.Name),\r\n 'Free',\r\n '',\r\n '',\r\n '',\r\n context,\r\n (data.category && data.category.result) || undefined\r\n );\r\n\r\n if (eventList && eventList.length !== 0) {\r\n return (\r\n \r\n );\r\n } else {\r\n console.log('Could not map product collection to product placement item succesfully');\r\n }\r\n }\r\n return this._renderNoEventsMessage();\r\n }\r\n\r\n // =============================================================================\r\n // JSX FRAGMENTS\r\n // =============================================================================\r\n\r\n // --------------------------------------------------------------\r\n // If no events are present, render this instead of the events\r\n // list\r\n // --------------------------------------------------------------\r\n private _renderNoEventsMessage(): JSX.Element {\r\n const { noEventsText } = this.props.config;\r\n\r\n const textToShow = noEventsText || 'No Events';\r\n\r\n return (\r\n // tslint:disable-next-line: react-no-dangerous-html\r\n \r\n );\r\n }\r\n\r\n // =============================================================================\r\n // PRIVATE METHODS\r\n // =============================================================================\r\n\r\n // --------------------------------------------------------------\r\n // Construct the event list data\r\n // --------------------------------------------------------------\r\n private _getEventListItems(): FullProduct[] {\r\n const { data } = this.props;\r\n let products: FullProduct[] = [];\r\n\r\n // TODO: May need to add refineSearch in future.\r\n // const refineSearchProducts = this.props.data.refineSearchProducts && this.props.data.refineSearchProducts.result;\r\n // if (refineSearchProducts && refineSearchProducts.refinementCriteria && refineSearchProducts.refinementCriteria.length) {\r\n // if (refineSearchProducts.productSearchResult && refineSearchProducts.productSearchResult.length) {\r\n // products = refineSearchProducts.productSearchResult;\r\n // }\r\n // }\r\n\r\n if (data.products && data.products.result && data.products.result.length > 0) {\r\n products = data.products.result;\r\n }\r\n\r\n return products;\r\n }\r\n}\r\n\r\nexport default EventList;","import { getProductPageUrlSync, getProductUrlSync } from '@msdyn365-commerce-modules/retail-actions';\r\nimport { CategoryHierarchy, FullProduct } from '@msdyn365-commerce/commerce-entities';\r\nimport { ICoreContext, IRequestContext } from '@msdyn365-commerce/core';\r\nimport { AttributeValue, ProductPrice, ProductRating, ProductSearchResult } from '@msdyn365-commerce/retail-proxy';\r\nexport interface IProductPlacementDataItem {\r\n description?: string;\r\n heading?: string;\r\n price?: IPrice;\r\n rating?: IRating;\r\n image?: string;\r\n productUrl?: string;\r\n recordId?: number;\r\n attributes?: AttributeValue[];\r\n}\r\nexport interface IPrice {\r\n locale: string;\r\n currencyCode: string;\r\n freePriceText: string;\r\n currentPrice?: IPriceRange;\r\n originalPrice?: IPriceRange;\r\n rangeFormatText?: string;\r\n savingsText?: string;\r\n originalPriceText: string;\r\n currentPriceText: string;\r\n}\r\n\r\nexport interface IRating {\r\n averageRating?: number;\r\n totalRatings?: number;\r\n ariaLabel?: string;\r\n}\r\n\r\nexport interface IPriceRange {\r\n startingValue: number;\r\n endingValue?: number;\r\n}\r\n\r\nexport function mapProductSearchResult(\r\n products: ProductSearchResult[],\r\n freePriceText: string,\r\n originalPriceText: string,\r\n currentPriceText: string,\r\n ratingAriaLabel: string,\r\n context: ICoreContext,\r\n CurrencyCode: string,\r\n category?: CategoryHierarchy\r\n): IProductPlacementDataItem[] {\r\n if (products && products.length > 0) {\r\n const productItems: IProductPlacementDataItem[] = [];\r\n products.map(product => {\r\n if (product && product !== undefined && product.RecordId !== undefined) {\r\n const productUrl = getProductPageUrlSync(product.Name || '', product.RecordId, context && context.actionContext, category);\r\n const item = {\r\n heading: product.Name,\r\n description: product.Description,\r\n price: mapProductSearchResultPrice(context.request, freePriceText, CurrencyCode, originalPriceText, currentPriceText, product.BasePrice, product.Price),\r\n rating: mapProductSearchResultRating(ratingAriaLabel, product.TotalRatings, product.AverageRating),\r\n image: product.PrimaryImageUrl,\r\n productUrl: productUrl,\r\n recordId: product.RecordId\r\n };\r\n productItems.push(item);\r\n }\r\n });\r\n return productItems;\r\n }\r\n return [];\r\n}\r\n\r\nfunction mapProductSearchResultPrice(\r\n requestContext: IRequestContext,\r\n freePriceText: string,\r\n currencyCode: string,\r\n originalPriceText: string,\r\n currentPriceText: string,\r\n productBasePrice?: number,\r\n productPrice?: number,\r\n): IPrice | undefined {\r\n if (productPrice !== undefined && requestContext) {\r\n return {\r\n locale: requestContext.locale,\r\n currencyCode: currencyCode,\r\n freePriceText: freePriceText,\r\n originalPriceText: originalPriceText,\r\n currentPriceText: currentPriceText,\r\n currentPrice: _mapNumberToIPriceRange(productPrice),\r\n originalPrice: _mapNumberToIPriceRange(productBasePrice)\r\n };\r\n }\r\n return undefined;\r\n}\r\n\r\nexport function mapProductCollection(\r\n products: FullProduct[],\r\n freePriceText: string,\r\n ratingAriaLabel: string,\r\n originalPriceText: string,\r\n currentPriceText: string,\r\n context: ICoreContext,\r\n category?: CategoryHierarchy\r\n): IProductPlacementDataItem[] {\r\n if(!products || products.length === 0) {\r\n return [];\r\n }\r\n\r\n const productItems: IProductPlacementDataItem[] = [];\r\n products.map(product => {\r\n if(product && product.ProductDetails) {\r\n const productUrl = getProductUrlSync(product.ProductDetails, context && context.actionContext, category);\r\n const item = {\r\n heading: product.ProductDetails.Name,\r\n description: product.ProductDetails.Description,\r\n price: mapProductPrice(product.ProductPrice, context.request, freePriceText, originalPriceText, currentPriceText),\r\n rating: mapProductRating(product.ProductRating, ratingAriaLabel),\r\n image: product.ProductDetails.PrimaryImageUrl,\r\n productUrl: productUrl,\r\n recordId: product.ProductDetails.RecordId,\r\n // @ts-ignore\r\n attributes: product.ProductAttributes\r\n };\r\n productItems.push(item);\r\n }\r\n });\r\n\r\n return productItems;\r\n}\r\n\r\nfunction mapProductPrice(\r\n productPrice: ProductPrice | undefined,\r\n requestContext: IRequestContext,\r\n freePriceText: string,\r\n originalPriceText: string,\r\n currentPriceText: string,\r\n): IPrice | undefined {\r\n if (productPrice && requestContext) {\r\n return {\r\n locale: requestContext.locale,\r\n currencyCode: productPrice.CurrencyCode ? productPrice.CurrencyCode : '',\r\n freePriceText: freePriceText,\r\n originalPriceText: originalPriceText,\r\n currentPriceText: currentPriceText,\r\n currentPrice: _mapNumberToIPriceRange(productPrice.CustomerContextualPrice),\r\n originalPrice: _mapNumberToIPriceRange(\r\n Math.max(productPrice.BasePrice || 0, productPrice.TradeAgreementPrice || 0, productPrice.AdjustedPrice || 0)\r\n )\r\n };\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction mapProductSearchResultRating(\r\n ariaLabel: string,\r\n productTotalRating?: number,\r\n productAverageRating?: number\r\n): IRating | undefined {\r\n if (productTotalRating && productAverageRating) {\r\n return {\r\n averageRating: productAverageRating,\r\n totalRatings: productTotalRating,\r\n ariaLabel: ariaLabel\r\n };\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction mapProductRating(\r\n productRating: ProductRating | undefined,\r\n ariaLabel: string\r\n): IRating | undefined {\r\n if (productRating) {\r\n return {\r\n averageRating: productRating.AverageRating || 0,\r\n totalRatings: productRating.TotalRatings || 0,\r\n ariaLabel: ariaLabel\r\n };\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction _mapNumberToIPriceRange(price: number | undefined): IPriceRange | undefined {\r\n if (price !== undefined) {\r\n return {\r\n startingValue: price\r\n };\r\n }\r\n return undefined;\r\n}\r\n"],"sourceRoot":""}