{"version":3,"file":"static/js/1802.62fdb777.chunk.js","mappings":"2WAwCA,SAASA,EAA2BC,GASnC,MAR+C,CAC9CA,MAAOA,EACPC,WAAY,GACZC,cAAe,EACfC,0BAA0B,EAC1BC,oBAAoB,EACpBC,0BAA0B,EAG5B,CAwKO,SAASC,EAAaC,EAAeP,GAC3C,YAAiCQ,IAA1BD,EAAME,kBAAsE,IAArCF,EAAME,gBAAgBC,IAAIV,EACzE,CAoCA,SAASW,EACRJ,EACAK,EACAC,GAEA,MAAM,MACLb,EAAK,WACLC,EAAU,cACVC,EAAa,yBACbC,EAAwB,mBACxBC,EAAkB,yBAClBC,GACGO,EACJ,IAAKN,EAAaC,EAAOP,KAzC1B,SAAuBO,EAAeP,GACrC,YAA4BQ,IAArBD,EAAMO,iBAA4DN,IAAhCD,EAAMO,WAAWJ,IAAIV,EAC/D,CAuCqCe,CAAcR,EAAOP,GACxD,MAAO,GAER,IAAIgB,EAAOT,EAAMO,WAAYJ,IAAIV,GAwBjC,OAtBIG,GAA4Ba,EAAKC,OAAS,IAC7CD,EAAOA,EAAKE,QAAQC,GAAMA,EAAEC,YAAclB,KAGvCE,GAAsBY,EAAKC,OAAS,IACvCD,EAAOA,EAAKE,QAAQC,GAAsC,OAAhCA,EAAEE,QAAQC,sBAGhCjB,GAA4BW,EAAKC,OAAS,IAC9CD,EAAOA,EAAKE,QACVC,IAAOA,EAAEI,eAAiBJ,EAAEE,QAAQG,sBAAwBL,EAAEE,QAAQI,qBAIrEZ,GAAYG,EAAKC,OAAS,IAC7BD,EAAOA,EAAKE,OAAOL,IAGhBZ,GAAce,EAAKC,OAAS,IAC/BD,EAAOA,EAAKE,QAAQC,GAvDtB,SAA4BlB,EAAoByB,GAC/C,OACCC,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAIE,WAC/BD,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAIG,gBAC/BF,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAII,gBAEjC,CAiD4BC,CAAmB9B,EAAYkB,MAGnDH,CACR,CAmDA,MAAMgB,GAAaC,EAAAA,EAAAA,kBAAiB,CACnCC,KApSM,WACN,MAAO,CACNzB,qBAAiBD,EACjBM,gBAAYN,EACZ2B,4BAAwB3B,EACxB4B,kCAAkC,EAEpC,EA8RCC,SAAU,CACTC,oBA1PK,SACN/B,EACAgC,GAOA,MAAM,MAAEvC,EAAK,KAAEgB,EAAI,sBAAEwB,EAAqB,yBAAEC,GAA6BF,EAGzE,IAAIG,EAAYnC,EAAME,gBACnB,IAAIkC,IAAqB,IAAIC,MAAMC,KAAKtC,EAAME,iBAAkB,CAACT,GAAO,KACxE,IAAI2C,IAAqB,CAAC,CAAC3C,GAAO,KAErC,MAAM8C,EAAkB9B,EAAK+B,KAAK5B,GA5CnC,SAAwBO,GACvB,MAAO,IACHA,EACHsB,UAAWtB,EAAIsB,WAAa,IAAIC,KAAKvB,EAAIsB,WACzC3B,SAS0B6B,EATExB,EAAIL,QAU1B,IACH6B,EACHC,kBAAmBD,EAAIC,mBAAqB,IAAIF,KAAKC,EAAIC,mBACzDC,eAAgBF,EAAIE,gBAAkB,IAAIH,KAAKC,EAAIE,gBACnDC,kBAAmBH,EAAIG,mBAAqB,IAAIJ,KAAKC,EAAIG,sBAL3D,IAA4BH,CAP5B,CAsCyCI,CAAenC,KAcvD,MAAO,CACNV,gBAAiBiC,EACjB5B,WAbeP,EAAMO,WACnB,IAAI6B,IAA6B,IAAIC,MAAMC,KAAKtC,EAAMO,YAAa,CAACd,EAAO8C,KAC3E,IAAIH,IAA6B,CAAC,CAAC3C,EAAO8C,KAY5CX,uBAVmB5B,EAAM4B,uBACvB,IAAIQ,IAA2B,IAC5BC,MAAMC,KAAKtC,EAAM4B,wBACpB,CAACnC,EAAOwC,KAER,IAAIG,IAA2B,CAAC,CAAC3C,EAAOwC,KAM1CJ,iCAAkCK,EAEpC,EAuNEc,eArNK,SAAwBhD,EAAegC,GAC7C,MAAM,MAAEiB,EAAK,MAAExD,GAAUuC,EAEnBkB,EADc9C,EAAcJ,EAAOR,EAA2BC,IACpC+C,KAAKrB,GACpCA,EAAI8B,QAAUA,EACX9B,EACA,IACGA,EACHgC,OAAQC,EAAAA,GAAwBC,YAIpC,MAAO,CACNnD,gBAAiBF,EAAME,gBACvB0B,uBAAwB5B,EAAM4B,uBAC9BrB,WAAY,IAAI6B,IAA6B,IACzCC,MAAMC,KAAKtC,EAAMO,YACpB,CAACd,EAAOyD,KAETrB,iCAAkC7B,EAAM6B,iCAE1C,EAiMEyB,oBAzLK,SACNtD,EACAgC,GAOA,MAAM,MAAEiB,EAAK,MAAExD,EAAK,WAAE8D,EAAU,QAAEC,GAAYxB,EACxCyB,EAAcrD,EAAcJ,EAAOR,EAA2BC,IAC9DiE,EAA0B,OAAfH,EACXL,EAAcO,EAAYjB,KAAKrB,GACpCA,EAAI8B,QAAUA,EACX9B,EACA,IACGA,EACHL,QAAS,IACLK,EAAIL,QACPC,kBAAmBwC,EACnBI,qBAAsBD,EAAW,KAAOF,EAGxCV,kBAAmBY,EAAW,KAAO,IAAIhB,KACzCkB,0BAA2BF,EAAW,KAAO,UAKlD,MAAO,CACNxD,gBAAiBF,EAAME,gBACvB0B,uBAAwB5B,EAAM4B,uBAC9BrB,WAAY,IAAI6B,IAA6B,IACzCC,MAAMC,KAAKtC,EAAMO,YACpB,CAACd,EAAOyD,KAETrB,iCAAkC7B,EAAM6B,iCAE1C,GAqJCgC,UAAW,CACV9D,eACA+D,aArDK,SAAsB9D,EAAeK,GAM3C,OALaD,EACZJ,EACAK,GACCO,IAAOA,EAAEE,QAAQG,uBAAyBL,EAAEE,QAAQI,oBAE1C6C,MAAK,CAACnD,EAAGoD,IAAMpD,EAAES,QAAQ4C,cAAcD,EAAE3C,UACtD,EA+CE6C,2BAxCK,SACNlE,EACAK,GAOA,OALaD,EACZJ,EACAK,GACCO,IAAyC,IAAnCA,EAAEE,QAAQG,uBAAkCL,EAAEE,QAAQI,oBAElD6C,MAAK,CAACnD,EAAGoD,IAAMpD,EAAES,QAAQ4C,cAAcD,EAAE3C,UACtD,EA+BE8C,wBAxBK,SAAiCnE,EAAeK,GAEtD,OADaD,EAAcJ,EAAOK,GAAeO,IAAsC,IAAhCA,EAAEE,QAAQI,oBACrD6C,MAAK,CAACnD,EAAGoD,IAAMpD,EAAES,QAAQ4C,cAAcD,EAAE3C,UACtD,EAsBE+C,yBA1IK,SAAkCpE,EAAeP,GACvD,QAAqCQ,IAAjCD,EAAM4B,uBACT,OAAO5B,EAAM4B,uBAAuBzB,IAAIV,EAE1C,EAuIE4E,oCArBK,SAA6CrE,GACnD,OAAOA,EAAM6B,gCACd,KAuBAyC,EAAAA,EAAMC,eAAe9C,EAAW+C,YAAa,iBAEtC,MAAQC,eAAgBC,EAAsBC,eAAgBC,GAA0BnD,EC9VxF,SAASM,EACf8C,EACApF,EACAgB,EACAwB,EACAC,GAEA2C,EACCH,EAAqB3C,oBAAoB,CACxCtC,QACAgB,OACAwB,wBACAC,6BAGH,C,mJCEA,SAAS4C,EAAuBvB,GAC/B,OAAQA,GACP,KAAKwB,EAAAA,GAA6BC,kBACjC,MAAO,kCACR,KAAKD,EAAAA,GAA6BE,eACjC,MAAO,8BACR,KAAKF,EAAAA,GAA6BG,wBACjC,MAAO,kDACR,KAAKH,EAAAA,GAA6BI,qBACjC,MAAO,8CACR,QACC,MAAO,GAEV,CAaO,MAAMC,GAA8BC,EAAAA,EAAAA,OAAMC,IAAmB,IAADC,EAClE,MAAM,IACLpE,EAAG,aACHqE,EAAY,QACZC,EAAO,MACPhG,EAAK,SACLoF,EAAQ,sBACR5C,EAAqB,yBACrBC,GACGoD,EAGEI,IAAoBvE,EAAIH,cACxB2E,EAAaH,EAAaI,eAAc,GAAAC,OACxCJ,EAAO,yBACVD,EAAaM,qBAAuBN,EAAaO,qBAAoB,GAAAF,OAClEJ,EAAO,2BACV,GAEGO,EAAYL,EAAWjF,OAAS,EAChCuF,EAAQ,GAAAJ,OAAMJ,EAAO,gBAAAI,OAAepG,EAAK,cAAAoG,OAAa1E,EAAIG,cAC1D4E,EAAU,GAAAL,OAAMJ,EAAO,qBAAAI,OAAoBpG,EAAK,cAAAoG,OAAa1E,EAAIG,cACjE6E,EAAqBhF,EAAI8B,QAAU9B,EAAIiF,iBACvCC,EACLlF,EAAIgC,SAAWC,EAAAA,GAAwBC,UAAYlC,EAAIgC,SAAWC,EAAAA,GAAwBkD,QACpFC,EAAaC,IAAkBC,EAAAA,EAAAA,UAAmC,OACnE,SAAEC,IAAaC,EAAAA,EAAAA,KAAkB9C,GAAcA,EAAU+C,YAAY,IAErEC,GAAeC,EAAAA,EAAAA,UAAQ,IAAM,IAAIC,EAAAA,GAAmB5F,EAAIL,UAAU,CAACK,EAAIL,UACvEkG,GAAWF,EAAAA,EAAAA,UAChB,IACCD,EAAaI,sBACXC,EAAAA,EAAAA,IAAc/F,EAAIgG,2BAClBD,EAAAA,EAAAA,IAAc/F,EAAIiG,wBAErB,CAACjG,EAAIgG,wBAAyBhG,EAAIiG,qBAAsBP,IAEnDQ,GACJlB,GAAsBa,GAAY7F,EAAImG,mBAAqBnG,EAAIoG,oBAE3DC,GAAqBC,EAAAA,EAAAA,cAAY,ID5DjC,SAAwB5C,EAAqB5B,EAAexD,GAClEoF,EAASH,EAAqB1B,eAAe,CAAEC,QAAOxD,UACvD,CC0D8CuD,CAAe6B,EAAU1D,EAAI8B,MAAOxD,IAAQ,CACxF0B,EAAI8B,MACJ4B,EACApF,IAIKiI,GAA4BD,EAAAA,EAAAA,cACjC,CACCxE,EACAxD,EACA8D,EACAoE,ID9DI,SACN9C,EACA5B,EACAxD,EACA8D,EACAC,GAEAqB,EAASH,EAAqBpB,oBAAoB,CAAEL,QAAOxD,QAAO8D,aAAYC,YAC/E,CCuDOF,CAAoBuB,EAAU5B,EAAOxD,EAAO8D,EAAYoE,IAC7D,CAAC9C,IAGI+C,GAAsBH,EAAAA,EAAAA,cAC1BI,GACA9F,EACC8C,EACApF,EACAoI,EAASC,cACTD,EAAS5F,sBACT4F,EAAShG,mCAEX,CAACgD,EAAUpF,KAGLsI,IAA2BC,EAAAA,EAAAA,UAASC,GAAgB,CAC1DC,mBAAoBxB,EAASyB,gCAC7BC,YAAa,mBACbC,UAAYR,IACXrB,EAAeqB,EAAStB,YAAY,EAErC+B,iBAAkB,CAACnH,EAAI8B,SAGlBsF,GACJpH,EAAIqH,kBAAiB,cAAA3C,OAAiB1E,EAAIqH,kBAAiB,QAAS,eAAa,GAAA3C,OAC/E1E,EAAIsB,UAAUgG,qBAAoB,KAKhCC,EACL,iCACExB,EAAAA,EAAAA,IAAc/F,EAAIL,QAAQ6H,2BAIzB,IAJmD,OAAA9C,OAEnD1E,EAAIL,QAAQ6H,0BAAyB,QAAA9C,OAC9B1E,EAAIL,QAAQ8B,kBAAmB6F,qBAAoB,MAGxDG,EACL,6BACE1B,EAAAA,EAAAA,IAAc/F,EAAIL,QAAQ+H,wBAIzB,IAJgD,OAAAhD,OAEhD1E,EAAIL,QAAQ+H,uBAAsB,QAAAhD,OAC3B1E,EAAIL,QAAQ+B,eAAgB4F,qBAAoB,MAGrDK,GAAqB3H,EAAIL,QAAQG,uBAAyBE,EAAIL,QAAQI,kBAEtE6H,GAAuBC,EAAAA,EAAAA,IAAWjB,GAIxC,OACCkB,EAAAA,EAAAA,KAAAC,EAAAA,SAAA,CAAAC,UACCF,EAAAA,EAAAA,KAACG,EAAAA,GAAY,CACZnG,MAAO9B,EAAI8B,MACX5B,QAASF,EAAIE,QACbgI,SAAU3D,IAAmB4D,EAAAA,EAAAA,MAACC,EAAAA,GAAG,CAAAJ,SAAA,CAAC,cAAYhI,EAAIH,iBAClDwI,QAASxD,EAAYL,EAAaxE,EAAI8B,WAAQhD,EAC9CwJ,UAAWzD,EAAY,6BAA0B/F,EACjDyJ,kBAAkBT,EAAAA,EAAAA,KAACU,EAAAA,GAAY,CAACxG,OAAQhC,EAAIgC,OAAQyG,KAAK,OACzDC,mBACCP,EAAAA,EAAAA,MAACQ,EAAAA,GAAM,CAACC,QAAQ,QAAQC,MAAM,cAAab,SAAA,EAC1CF,EAAAA,EAAAA,KAACgB,EAAAA,GAAS,CACTC,EAAE,OACFC,MAAO,SACPC,eACCtB,EACCP,GAEAe,EAAAA,EAAAA,MAACe,EAAAA,GAAa,CAAAlB,SAAA,EACbF,EAAAA,EAAAA,KAACqB,EAAAA,GAAQ,CAAAnB,SAAEZ,IACVpH,EAAIL,QAAQG,uBACZgI,EAAAA,EAAAA,KAACqB,EAAAA,GAAQ,CAAAnB,SAAET,IAEXvH,EAAIL,QAAQI,oBACZ+H,EAAAA,EAAAA,KAACqB,EAAAA,GAAQ,CAAAnB,SAAEP,OAKf2B,KAAMC,EAAAA,IAG4B,OAAlCrJ,EAAIL,QAAQC,oBACZkI,EAAAA,EAAAA,KAACgB,EAAAA,GAAS,CACTC,EAAE,OACFC,MAAM,oBACNC,gBACCd,EAAAA,EAAAA,MAACC,EAAAA,GAAG,CAAAJ,SAAA,CACFhI,EAAIL,QAAQ8C,0BAA0B,2BAAyB,IAC/DkB,EAAuB3D,EAAIL,QAAQC,mBAAmB,MAAI,IAC7B,QADgCwE,EAC7DpE,EAAIL,QAAQgC,yBAAiB,IAAAyC,OAAA,EAA7BA,EAA+BkD,qBAAqB,IACpDtH,EAAIL,QAAQ6C,sBACZxC,EAAIL,QAAQ6C,qBAAqBjD,OAAS,IACzC4I,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,EACCG,EAAAA,EAAAA,MAACC,EAAAA,GAAG,CAACkB,GAAG,QAAOtB,SAAA,CAAC,6CAC4B,QAE5CF,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACkB,GAAG,QAAOtB,SAAEhI,EAAIL,QAAQ6C,6BAKlC4G,KAAMG,EAAAA,IACNC,UAAW,CAAEC,EAAG,OAAQV,EAAG,OAAQW,gBAAiB,WACpDC,aAAc,CACbZ,EAAG,CAAEa,KAAM,OAAQC,GAAI,QACvBC,KAAM,CAAEF,KAAM,OAAQC,GAAI,cAM/BE,cACC7D,IACCiC,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,EACGhD,IACAH,GACAiD,EAAAA,EAAAA,KAACkC,EAAAA,EAAc,CACdC,cAAezF,EAAaxE,EAAIiF,iBAChCnD,MAAO9B,EAAI8B,MACXoI,YAAalK,EAAIiF,iBACjBkF,UAAQ,KAGThC,EAAAA,EAAAA,MAACC,EAAAA,GAAG,CAACgC,MAAM,qCAAoCpC,SAAA,EAC9CF,EAAAA,EAAAA,KAACuC,EAAAA,IAAU,CACVC,MAAO,CAAEC,QAAS,eAAgBC,YAAa,OAC/CC,MAAM,UACL,wBAIJ5E,IACAiC,EAAAA,EAAAA,KAAC4C,EAAAA,GAAkB,CAClBC,YAAa7J,EACbqJ,UAAU,EACVnE,wBAAyBhG,EAAIgG,wBAC7BC,qBAAsBjG,EAAIiG,qBAC1B2E,kCACClF,EAAakF,kCAEdC,kCACCnF,EAAamF,kCAEdC,qBAAsBpF,EAAaoF,qBACnCC,qBAAsBrF,EAAaqF,qBACnCC,uBAAwBtF,EAAasF,uBACrCC,uBAAwBvF,EAAauF,yBAGtCjL,EAAImG,oBACJgC,EAAAA,EAAAA,MAAC+C,EAAAA,EAAM,CACNC,IAAKrG,EACLsG,OAAO,SACPhB,MAAM,6CAA4CpC,SAAA,EAElDF,EAAAA,EAAAA,KAACuD,EAAAA,IAAW,CACXZ,MAAM,gBACNH,MAAO,CAAEC,QAAS,SAAUC,YAAa,SACxC,eAIHxK,EAAIoG,sBACJ+B,EAAAA,EAAAA,MAAC+C,EAAAA,EAAM,CACNC,IAAKpG,EACLqG,OAAO,SACPhB,MAAM,2DAA0DpC,SAAA,EAEhEF,EAAAA,EAAAA,KAACwD,EAAAA,IAAoB,CACpBb,MAAM,YACNH,MAAO,CAAEC,QAAS,SAAUC,YAAa,SACxC,wBAOPe,QACClH,EAAaI,iBACZ0D,EAAAA,EAAAA,MAACQ,EAAAA,GAAM,CAACI,EAAE,OAAOH,QAAQ,SAAQZ,SAAA,EAC9B9C,IAAiBX,IAClBuD,EAAAA,EAAAA,KAAC0D,EAAAA,GAAkB,CAClBpG,YAAaA,EACbwC,qBAAsBA,EACtB6D,UAAWzL,EAAIgC,OACf0J,eAAgBrF,EAChBvE,MAAO9B,EAAI8B,MACX6J,SAAUC,EAAAA,GACVC,qBAAsB7L,EAAI8L,oBAC1BC,6BAA8B/L,EAAIgM,kCAGnC3H,EAAa4H,qBACb9D,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,EACCF,EAAAA,EAAAA,KAACoE,EAAAA,GAA8B,CAC9BvM,QAAS+F,EACT+F,UAAWzL,EAAIgC,OACf2I,YAAa7J,EACbqL,cAAenM,EAAIoM,UACnBC,gBAAiBrM,EAAIsM,aACrBC,wBAAyBvM,EAAIwM,qBAC7BC,QAASC,EAAAA,GAAgBC,QACzBC,iBAAkBC,GAClBnB,eAAgBjF,EAChBkF,SAAUC,EAAAA,GACVkB,oBAAqB9M,EAAIgG,wBACzB6F,qBAAsB7L,EAAI8L,oBAC1BC,6BAA8B/L,EAAIgM,gCAClCe,kBAAmB/M,EAAI+M,kBACvBC,qCACChN,EAAIgN,qCAEL5H,YAAaA,EACb1E,iCAAkCK,EAClCwD,gBAAiBA,EACjB1E,cAAeG,EAAIH,cACnBoN,iBAAiB,EACjBC,UAAWtF,KAIT1C,GAAgBlF,EAAIL,QAAQG,sBAC9BE,EAAIL,QAAQI,qBACZ+H,EAAAA,EAAAA,KAACoE,EAAAA,GAA8B,CAC9BvM,QAAS+F,EACT+F,UAAWzL,EAAIgC,OACf2I,YAAa7J,EACbqL,cAAenM,EAAIoM,UACnBC,gBAAiBrM,EAAIsM,aACrBC,wBAAyBvM,EAAIwM,qBAC7BC,QAASC,EAAAA,GAAgBS,KACzBP,iBAAkBC,GAClBnB,eAAgBjF,EAChBkF,SAAUC,EAAAA,GACVkB,oBAAqB9M,EAAIiG,qBACzB4F,qBAAsB7L,EAAI8L,oBAC1BC,6BAA8B/L,EAAIgM,gCAClCe,kBAAmB/M,EAAI+M,kBACvBC,qCACChN,EAAIgN,qCAEL5H,YAAaA,EACb1E,iCAAkCK,EAClCwD,gBAAiBA,EACjB1E,cAAeG,EAAIH,cACnBoN,iBAAiB,EACjBC,UAAWtF,QAKb5H,EAAIgN,uCACLlF,EAAAA,EAAAA,KAACsF,EAAAA,GAA8B,CAC9B9O,MAAOA,EACPqB,QAASK,EAAIL,QACb+L,eAAgBnF,EAChBlC,aAAcA,EACdsH,SAAUC,EAAAA,WAOd,ICxWL,SAASyB,IAAkD,IAAD,IAAAC,EAAAC,UAAAhO,OAAzBiO,EAAI,IAAAtM,MAAAoM,GAAAG,EAAA,EAAAA,EAAAH,EAAAG,IAAJD,EAAIC,GAAAF,UAAAE,GACpC,OAAOD,EAAKhO,QAAQC,IAAY,IAANA,IAAYF,MACvC,CAGO,MAAMmO,EAAgCvJ,IAC5C,MAAM,WACLwJ,EAAU,MACVrP,EAAK,aACL+F,EAAY,gBACZuJ,EAAe,0BACfC,EAAyB,kBACzBC,GACG3J,GAGG5F,EAAYwP,IAAiBzI,EAAAA,EAAAA,UAAiB,IAC/C0I,GAAyB1H,EAAAA,EAAAA,cAAa2H,GAA0BF,EAAcE,IAAgB,KAC7FxP,EAA0ByP,IAA+B5I,EAAAA,EAAAA,WAAkB,IAC3E5G,EAAoByP,IAAyB7I,EAAAA,EAAAA,WAAkB,IAC/D3G,EAA0ByP,IAA+B9I,EAAAA,EAAAA,WAAkB,GAE5E+I,GAAoC/H,EAAAA,EAAAA,cACxCgI,IACA,MAAMC,EAA8BD,EAAGlD,OAAOoD,QAC9CX,GACCA,EACCR,EACCkB,EACA7P,EACAC,IAGHuP,EAA4BK,EAA4B,GAEzD,CAAC7P,EAAoBC,EAA0BkP,IAG1CY,GAAkCnI,EAAAA,EAAAA,cACtCgI,IACA,MAAMI,EAA4BJ,EAAGlD,OAAOoD,QAC5CX,GACCA,EACCR,EACC5O,EACAiQ,EACA/P,IAGHwP,EAAsBO,EAA0B,GAEjD,CAACjQ,EAA0BE,EAA0BkP,IAGhDc,GAAwCrI,EAAAA,EAAAA,cAC5CgI,IACA,MAAM3P,EAA2B2P,EAAGlD,OAAOoD,QAC3CX,GACCA,EACCR,EACC5O,EACAC,EACAC,IAGHyP,EAA4BzP,EAAyB,GAEtD,CAACF,EAA0BC,EAAoBmP,IAG1CvJ,GAAUqB,EAAAA,EAAAA,UAAQ,KAAMiJ,EAAAA,EAAAA,OAAc,IACtCC,EAAiBC,EAAAA,EAAOC,UAAUC,qBAClCtL,GAAWuL,EAAAA,EAAAA,eAEXC,EAAYzL,GAAuBf,GAAcA,EAAU9D,aAAaN,IAAQ,CAACA,IAEjF6Q,EAAe,CACpB7Q,QACAC,aACAC,cAAe6F,EAAa+K,OAC5B3Q,2BACAC,qBACAC,4BAGK0Q,EAAY5L,GAAuBf,GAAcA,EAAUC,aAAawM,IAAe,CAC5FA,IAGKG,EAAsB7L,GAC1Bf,GAAcA,EAAUK,2BAA2BoM,IACpD,CAACA,IAGII,EAAmB9L,GACvBf,GAAcA,EAAUM,wBAAwBmM,IACjD,CAACA,IAGIK,EAAqB/L,GACzBf,GAAcA,EAAUO,yBAAyB3E,IAClD,CAACA,IAGIoC,EAAmC+C,GACvCf,GAAcA,EAAUQ,uCACzB,IAGKuM,GAA0BnJ,EAAAA,EAAAA,cAC/B,CAACI,EAAUgJ,KACV,MAAOpR,GAASoR,EAAO7O,OACvBD,EACC8C,EACApF,EACAoI,EAASC,cACTD,EAAS5F,sBACT4F,EAAShG,iCACT,GAEF,CAACgD,KAGKiM,EAAoBC,IAAY/I,EAAAA,EAAAA,UAASgJ,GAAkBC,EAAAA,GAAkB,CACnF/I,oBAAoB,EACpBE,YAAa,mBAIbC,UAAWA,CAACR,EAAUgJ,IAAWD,EAAwB/I,EAAUgJ,KAG9DK,GAAUpK,EAAAA,EAAAA,UACf,KACCwC,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,CACE3D,EAAaI,iBACbqD,EAAAA,EAAAA,KAACkI,EAAAA,EAAQ,CACRC,UAAWxR,EACXyR,SAAU7B,EACV9D,QAASoD,EAAa,cAAgB,OAAO3F,SAC7C,oBAIFF,EAAAA,EAAAA,KAACkI,EAAAA,EAAQ,CACRC,UAAWvR,EACXwR,SAAUzB,EACV0B,GAAIxC,GAActJ,EAAaI,eAAiB,WAAQ3F,EACxDyL,QAASoD,EAAa,cAAgB,OAAO3F,SAC7C,iCAGC3D,EAAa+L,YAAc/L,EAAagM,4BACzCvI,EAAAA,EAAAA,KAACkI,EAAAA,EAAQ,CACRC,UAAWtR,EACXuR,SAAUvB,EACVwB,GAAIxC,EAAa,WAAQ7O,EACzByL,QAASoD,EAAa,cAAgB,OACtCvD,MAAM,qLAAoLpC,SAC1L,qCAMJ,CACCtJ,EACAD,EACAgQ,EACAJ,EACAM,EACAhQ,EACAgP,EACAtJ,EAAagM,yBACbhM,EAAaI,eACbJ,EAAa+L,cAIfE,EAAAA,EAAAA,YAAU,KAGJpB,GACJU,EAAStR,GAIgB,IAAtBwP,IACCpP,GACHyP,GAAsB,GAEnB1P,GACHyP,GAA4B,GAGzBvP,GACHyP,GAA4B,IAK9BR,GAAmBA,EAAgBmC,EAAQ,GACzC,CACFb,EACAU,EACAtR,EACAwP,EACApP,EACAD,EACAmP,EACAmC,EACApR,IAKD,MAAM4R,EAAe,CACpB,CACCC,QAAS,SACTC,YAAapB,EAAU9P,OACvBmR,SACC,uGACDC,SACC7I,EAAAA,EAAAA,KAAC8I,EAAAA,GAAW,CACXC,iBAAiB,mBACjBhC,eAAiBlB,OAA8B7O,EAAjB+P,EAC9BlB,WAAYA,EAAW3F,SAEtBqH,EAAUhO,KAAKrB,IACf8H,EAAAA,EAAAA,KAAC7D,EAAe,CACfP,SAAUA,EACV1D,IAAKA,EAEL1B,MAAOA,EACPgG,QAASA,EACTD,aAAcA,EACdvD,sBAAuB0O,IAAuB,EAC9CzO,yBAA0BL,GALrBV,EAAI8B,YAWd,CACC0O,QAAS,aACTC,YAAanB,EAAoB/P,OACjCmR,SACC,gGACDC,SACC7I,EAAAA,EAAAA,KAAC8I,EAAAA,GAAW,CACXC,iBAAiB,mBACjBhC,eAAiBlB,OAA8B7O,EAAjB+P,EAC9BlB,WAAYA,EAAW3F,SAEtBsH,EAAoBjO,KAAKrB,IACzB8H,EAAAA,EAAAA,KAAC7D,EAAe,CACfP,SAAUA,EACV1D,IAAKA,EACL1B,MAAOA,EACP+F,aAAcA,EAEdC,QAASA,EACTxD,sBAAuB0O,IAAuB,EAC9CzO,yBAA0BL,GAHrBV,EAAI8B,YASd,CACC0O,QAAS,gBACTC,YAAalB,EAAiBhQ,OAC9BmR,SAAU,qFACVC,SACC7I,EAAAA,EAAAA,KAAC8I,EAAAA,GAAW,CACXC,iBAAiB,mBACjBhC,eAAiBlB,OAA8B7O,EAAjB+P,EAC9BlB,WAAYA,EAAW3F,SAEtBuH,EAAiBlO,KAAKrB,IACtB8H,EAAAA,EAAAA,KAAC7D,EAAe,CACfP,SAAUA,EACV1D,IAAKA,EACL1B,MAAOA,EACP+F,aAAcA,EAEdC,QAASA,EACTxD,sBAAuB0O,IAAuB,EAC9CzO,yBAA0BL,GAHrBV,EAAI8B,aAWf,OACCqG,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,CACE2F,IACA7F,EAAAA,EAAAA,KAACgJ,EAAAA,GAAW,CACXC,YAAY,2CACZC,iBAAkBhD,EAClBiD,gBAAiB,CAAEC,GAAI,WAGzB/I,EAAAA,EAAAA,MAACwH,EAAkB,CAClBwB,qBAAqBrJ,EAAAA,EAAAA,KAACsJ,EAAAA,GAAa,IACnCC,aAAa,qCACbC,yBAAuB,EAAAtJ,SAAA,CAEtB2F,IACA7F,EAAAA,EAAAA,KAAAC,EAAAA,SAAA,CAAAC,UACCG,EAAAA,EAAAA,MAACC,EAAAA,GAAG,CAAC8I,GAAG,SAAQlJ,SAAA,EACfG,EAAAA,EAAAA,MAACoJ,EAAAA,EAAI,CAACC,GAAG,OAAOC,GAAG,QAAOzJ,SAAA,CAAC,aACf,OAEX+H,QAIJjI,EAAAA,EAAAA,KAAC4J,EAAAA,GAAa,CAACnB,KAAMA,SAEpB,ECzSL,SAASoB,EAAY3R,GACpB,MAAO,IACHA,EACH4R,gBAAiB,CAChBC,SAAU7R,EAAI4R,gBAAgBC,SAC9BC,QAAS,IAAIvQ,KAAKvB,EAAI4R,gBAAgBE,UAEvCrQ,kBAAmBzB,EAAIyB,mBAAqB,IAAIF,KAAKvB,EAAIyB,mBACzDC,eAAgB1B,EAAI0B,gBAAkB,IAAIH,KAAKvB,EAAI0B,gBAErD,CAgGO,SAAS9C,EAAaC,EAAeP,GAC3C,YAAiCQ,IAA1BD,EAAME,kBAAsE,IAArCF,EAAME,gBAAgBC,IAAIV,EACzE,CAEA,SAASe,EAAcR,EAAeP,GACrC,YAA4BQ,IAArBD,EAAMO,iBAA4DN,IAAhCD,EAAMO,WAAWJ,IAAIV,EAC/D,CA2BA,SAASW,EACRJ,EACAP,EACAC,EACAY,GAEA,IAAKP,EAAaC,EAAOP,KAAWe,EAAcR,EAAOP,GACxD,MAAO,GAER,IAAIgB,EAAOT,EAAMO,WAAYJ,IAAIV,GASjC,OARIa,GAAYG,EAAKC,OAAS,IAC7BD,EAAOA,EAAKE,OAAOL,IAGhBZ,GAAce,EAAKC,OAAS,IAC/BD,EAAOA,EAAKE,QAAQC,GAlCtB,SAA4BlB,EAAoByB,GAC/C,OACCC,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAIE,WAC/BD,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAI+R,cAC/B9R,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAIG,gBAC/BF,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAII,gBAEjC,CA2B4BC,CAAmB9B,EAAYkB,MAGnDH,CACR,CD+IAoO,EAAoBsE,WAAa,gBCjFjC,MAAM1R,GAAaC,EAAAA,EAAAA,kBAAiB,CACnCC,KA3OM,WACN,MAAO,CACNzB,qBAAiBD,EACjBM,gBAAYN,EAEd,EAuOC6B,SAAU,CACTC,oBA7MK,SACN/B,EACAgC,GAEA,MAAM,MAAEvC,EAAK,KAAEgB,GAASuB,EAGxB,IAAIG,EAAYnC,EAAME,gBACnB,IAAIkC,IAAqB,IAAIC,MAAMC,KAAKtC,EAAME,iBAAkB,CAACT,GAAO,KACxE,IAAI2C,IAAqB,CAAC,CAAC3C,GAAO,KAErC,MAAM8C,EAAkB9B,EAAK+B,KAAK5B,GAAMkS,EAAYlS,KAOpD,MAAO,CACNV,gBAAiBiC,EACjB5B,WANeP,EAAMO,WACnB,IAAI6B,IAA8B,IAAIC,MAAMC,KAAKtC,EAAMO,YAAa,CAACd,EAAO8C,KAC5E,IAAIH,IAA8B,CAAC,CAAC3C,EAAO8C,KAM/C,EAwLE6Q,oBAhLK,SACNpT,EACAgC,GAEA,MAAM,MAAEiB,EAAK,MAAExD,EAAK,UAAE4T,GAAcrR,EAE9BkB,EADc9C,EAAcJ,EAAOP,EAAO,QAAIQ,GACpBuC,KAAKrB,GACpCA,EAAI8B,QAAUA,EAAQ9B,EAAM,IAAKA,EAAKmS,cAAeD,KAGtD,MAAO,CACNnT,gBAAiBF,EAAME,gBACvBK,WAAY,IAAI6B,IAA8B,IAC1CC,MAAMC,KAAKtC,EAAMO,YACpB,CAACd,EAAOyD,KAGX,EAgKEqQ,gBAxJK,SAAyBvT,EAAegC,GAC9C,MAAM,MAAEvC,EAAK,IAAE0B,GAAQa,EAEvB,IAAKjC,EAAaC,EAAOP,KAAWe,EAAcR,EAAOP,GACxD,OAAOO,EAGR,MAEMuC,EAAkB,IAFLnC,EAAcJ,EAAOP,EAAO,QAAIQ,GAClC6S,EAAY3R,IAIvBqS,EAAU,IAAIpR,IAA8B,IAC9CC,MAAMC,KAAKtC,EAAMO,YACpB,CAACd,EAAO8C,KAGT,MAAO,CACNrC,gBAAiBF,EAAME,gBACvBK,WAAYiT,EAEd,GAqIC3P,UAAW,CACV9D,aAAY,EACZ0T,kBA/CK,SAA2BzT,EAAegC,GAChD,MAAM,MAAEvC,EAAK,WAAEC,GAAesC,EAU9B,OATa5B,EACZJ,EACAP,EACAC,GACCkB,IACCA,EAAE8S,yBAA2BC,EAAAA,GAAuBC,UACpDhT,EAAE8S,yBAA2BC,EAAAA,GAAuBE,eAChC,OAApBjT,EAAE0S,eAA0B1S,EAAE0S,gBAAkBQ,EAAAA,GAAcC,cAErDhQ,MAAK,CAACnD,EAAGoD,IAAMpD,EAAES,QAAQ4C,cAAcD,EAAE3C,UACtD,EAoCE2S,uBAjEK,SAAgChU,EAAegC,GACrD,MAAM,MAAEvC,EAAK,WAAEC,GAAesC,EAO9B,OANa5B,EACZJ,EACAP,EACAC,GACCkB,GAAMA,EAAE8S,yBAA2BC,EAAAA,GAAuBM,aAEhDlQ,MAAK,CAACnD,EAAGoD,IAAMpD,EAAES,QAAQ4C,cAAcD,EAAE3C,UACtD,EAyDE6S,oBA7BK,SAA6BlU,EAAegC,GAClD,MAAM,MAAEvC,EAAK,WAAEC,GAAesC,EAU9B,OATa5B,EACZJ,EACAP,EACAC,GACCkB,IACCA,EAAE8S,yBAA2BC,EAAAA,GAAuBC,UACpDhT,EAAE8S,yBAA2BC,EAAAA,GAAuBE,cACrDjT,EAAE0S,gBAAkBQ,EAAAA,GAAcK,aAExBpQ,MAAK,CAACnD,EAAGoD,IAAMpD,EAAES,QAAQ4C,cAAcD,EAAE3C,UACtD,KAoBAiD,EAAAA,EAAMC,eAAe9C,EAAW+C,YAAa,kBAEtC,MAAQC,eAAgB2P,EAAuBzP,eAAgB0P,GAA2B5S,E,qCCvK1F,SAAS1B,EAAaC,EAAeP,GAC3C,YAAiCQ,IAA1BD,EAAME,kBAAsE,IAArCF,EAAME,gBAAgBC,IAAIV,EACzE,CAEA,SAASe,EAAcR,EAAeP,GACrC,YAA4BQ,IAArBD,EAAMO,iBAA4DN,IAAhCD,EAAMO,WAAWJ,IAAIV,EAC/D,CA2BA,SAASW,EACRJ,EACAP,EACAC,EACAY,GAEA,IAAKP,EAAaC,EAAOP,KAAWe,EAAcR,EAAOP,GACxD,MAAO,GAER,IAAIgB,EAAOT,EAAMO,WAAYJ,IAAIV,GASjC,OARIa,GAAYG,EAAKC,OAAS,IAC7BD,EAAOA,EAAKE,OAAOL,IAGhBZ,GAAce,EAAKC,OAAS,IAC/BD,EAAOA,EAAKE,QAAQC,GAlCtB,SAA4BlB,EAAoByB,GAC/C,OACCC,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAIE,WAC/BD,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAI+R,cAC/B9R,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAIG,gBAC/BF,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAII,gBAEjC,CA2B4BC,CAAmB9B,EAAYkB,MAGnDH,CACR,CA2DA,MAAMgB,GAAaC,EAAAA,EAAAA,kBAAiB,CACnCC,KApMM,WACN,MAAO,CACNzB,qBAAiBD,EACjBM,gBAAYN,EAEd,EAgMC6B,SAAU,CACTC,oBA3KK,SAA6B/B,EAAegC,GAClD,MAAM,MAAEvC,EAAK,KAAEgB,GAASuB,EAGxB,IAAIG,EAAYnC,EAAME,gBACnB,IAAIkC,IAAqB,IAAIC,MAAMC,KAAKtC,EAAME,iBAAkB,CAACT,GAAO,KACxE,IAAI2C,IAAqB,CAAC,CAAC3C,GAAO,KAErC,MAAM8C,EAAkB9B,EAAK+B,KAAK5B,IAAMkS,OArBpB3R,EAqBgCP,EApB7C,IACHO,EACHmT,aAAcnT,EAAImT,cAAgB,IAAI5R,KAAKvB,EAAImT,eAHjD,IAAqBnT,CAqBkC,IAOtD,MAAO,CACNjB,gBAAiBiC,EACjB5B,WANeP,EAAMO,WACnB,IAAI6B,IAAwB,IAAIC,MAAMC,KAAKtC,EAAMO,YAAa,CAACd,EAAO8C,KACtE,IAAIH,IAAwB,CAAC,CAAC3C,EAAO8C,KAMzC,EAyJEgS,YAlJK,SAAqBvU,EAAeP,GAC1C,IAAKM,EAAaC,EAAOP,KAAWe,EAAcR,EAAOP,GACxD,OAAOO,EAIR,MAAMwT,EAAU,IAAIpR,IAAwB,IACxCC,MAAMC,KAAKtC,EAAMO,YAElBI,QAAQJ,GAAeA,EAAW,KAAOd,MAM5C,MAAO,CACNS,gBALiB,IAAIkC,IAAqB,IACvCC,MAAMC,KAAKtC,EAAME,iBAAkBS,QAAQ6T,GAAiBA,EAAa,KAAO/U,MAKnFc,WAAYiT,EAEd,GAiIC3P,UAAW,CACV9D,aAAY,EACZ0U,WA5DK,SAAoBzU,EAAegC,GACzC,MAAM,MAAEvC,EAAK,WAAEC,GAAesC,EAE9B,OADa5B,EAAcJ,EAAOP,EAAOC,OAAYO,GACzC8D,MAAK,CAACnD,EAAGoD,IAAMpD,EAAES,QAAQ4C,cAAcD,EAAE3C,UACtD,EAyDEqT,sBAlDK,SAA+B1U,EAAegC,GACpD,MAAM,MAAEvC,EAAK,WAAEC,GAAesC,EAE9B,OADa5B,EAAcJ,EAAOP,EAAOC,GAAakB,GAA6B,IAAvBA,EAAE+T,mBAClD5Q,MAAK,CAACnD,EAAGoD,IAAMpD,EAAES,QAAQ4C,cAAcD,EAAE3C,UACtD,EA+CEuT,4BAxCK,SACN5U,EACAgC,GAEA,MAAM,MAAEvC,EAAK,UAAEoV,GAAc7S,EAE7B,IAAKjC,EAAaC,EAAOP,KAAWe,EAAcR,EAAOP,GACxD,OAGD,MAAMqV,EAAQ,IAAIpS,KACZqS,EAAiB,IAAIrS,KAC1BoS,EAAME,cACNF,EAAMG,WAAaJ,EACnBC,EAAMI,UACLC,UAQF,OANa/U,EACZJ,EACAP,EACA,IACCmB,GAAyB,OAAnBA,EAAE0T,cAAyB1T,EAAE0T,aAAaa,WAAaJ,IAEnDrU,MACb,KAmBA4D,EAAAA,EAAMC,eAAe9C,EAAW+C,YAAa,YAEtC,MAAQC,eAAgB2Q,EAAiBzQ,eAAgB0Q,GAAqB5T,E,gBC/N9E,MAAM6T,IAAmCjQ,EAAAA,EAAAA,OAAMC,IACrD,MAAM,kBAAE1C,EAAiB,eAAEC,EAAc,mBAAE0S,GAAuBjQ,EAElE,OAAI1C,IAAsBC,GAExBoG,EAAAA,EAAAA,KAACgB,EAAAA,GAAS,CACTE,MAAM,6BACNC,eAAc,iCAAAvE,OAAmCjD,EAAkB6F,sBACnE8B,KAAMiL,GAAAA,IAGE5S,GAAqBC,GAE9BoG,EAAAA,EAAAA,KAAAC,EAAAA,SAAA,CAAAC,UACCF,EAAAA,EAAAA,KAACgB,EAAAA,GAAS,CACTE,MAAOoL,EAAqB,yBAA2B,+BACvDnL,gBACCd,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,EACGoM,IACDjM,EAAAA,EAAAA,MAACC,EAAAA,GAAG,CAAAJ,SAAA,CAAC,iCAC2BvG,EAAkB6F,yBAGnDa,EAAAA,EAAAA,MAACC,EAAAA,GAAG,CAAAJ,SAAA,CAAC,6BAA2BtG,EAAe4F,2BAGjD8B,KAAMiL,GAAAA,OAIE5S,GAAqBC,GAG/BoG,EAAAA,EAAAA,KAACgB,EAAAA,GAAS,CACTE,MAAOoL,EAAqB,yBAA2B,+BACvDnL,eAAc,eAAAvE,OACb0P,EAAqB,aAAe,mBAAkB,QAAA1P,OAChDhD,EAAe4F,sBACtB8B,KAAMiL,GAAAA,IAID,IACR,IC3BYC,IAA8CpQ,EAAAA,EAAAA,OAAMC,IAAkC,IAADoQ,EAAAC,EAAAC,EACjG,MAAM,aAAEpQ,EAAY,IAAErE,EAAG,QAAEsE,EAAO,MAAEhG,EAAK,SAAEoF,GAAaS,GAElD,SAAEoB,IAAaC,EAAAA,EAAAA,KAAkB9C,GAAcA,EAAU+C,YAAY,IAErEiP,EAAc,GAAAhQ,OAAMa,EAASoP,YAAW,kBACxCC,EAAW,gBAEXC,EAAa,GAAAnQ,OAAMJ,EAAO,qCAC1BU,EAAqBhF,EAAI8B,QAAU9B,EAAIiF,iBACvC6P,EAAe9U,EAAIuS,yBAA2BC,EAAAA,GAAuBM,WACrEiC,EAAgB/U,EAAIgV,wBAAwBzV,OAAS,EACrD2G,EACJ6O,IAAkBD,IAAkB9P,GAAsBhF,EAAIiV,uBAE1DC,GAAmBlV,EAAImV,qBAAuBT,EAAiBE,GAAe5U,EAAI8B,MAClFsT,GACJpV,EAAIqV,kCAAoCX,EAAiBE,GAAe5U,EAAIiF,kBAGvEqQ,EAAYC,IAAiBjQ,EAAAA,EAAAA,UAAoD,MAElFkQ,GAAsBlP,EAAAA,EAAAA,cAC1BmP,GAAuDF,EAAcE,IACtE,IAEKC,GAAmCpP,EAAAA,EAAAA,cACvC4L,KCnCI,SACNxO,EACA5B,EACAxD,EACA4T,GAEAxO,EAASuP,EAAsBhB,oBAAoB,CAAEnQ,QAAOxD,QAAO4T,cACpE,CD6BGyD,CAA2BjS,EAAU1D,EAAI8B,MAAOxD,EAAO4T,GAGnDA,IAAcS,EAAAA,GAAciD,MEzC5B,SAAqBlS,EAAqBpF,GAChDoF,EAASuQ,EAAgBb,YAAY9U,GACtC,CFwCI8U,CAAY1P,EAAUpF,EACvB,GAED,CAAC0B,EAAI8B,MAAO4B,EAAUpF,IAGvB,OACCwJ,EAAAA,EAAAA,KAAAC,EAAAA,SAAA,CAAAC,UACCF,EAAAA,EAAAA,KAACG,EAAAA,GAAY,CACZnG,MAAO9B,EAAI8B,MACX5B,QAASF,EAAIE,QACbgI,UAAUJ,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACgC,MAAM,yCAAwCpC,SAAEhI,EAAI+R,aACnE1J,QAAS6M,EACTW,iBAAkBL,EAClBlN,UAAU,0BACVC,kBACCJ,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,CACEhI,EAAI8V,mBACJhO,EAAAA,EAAAA,KAACiO,EAAAA,EAAK,CACLC,IAAKnB,EACLpL,EAAE,OACFV,EAAE,OACFqB,MAAM,qCACN,aAAW,oCACX6L,IAAI,iBACJ1L,QAAQ,iBAITwK,IAAiBjN,EAAAA,EAAAA,KAACoO,EAAAA,GAAiB,OAGtCxN,mBACCZ,EAAAA,EAAAA,KAACqO,EAAAA,GAAI,CAACvN,QAAQ,QAAQ2B,QAAQ,eAAcvC,SAC1C8M,GACAhN,EAAAA,EAAAA,KAACqB,EAAAA,GAAQ,CAAAnB,UACRF,EAAAA,EAAAA,KAACgB,EAAAA,GAAS,CACTE,MAAM,qBACNC,eACC,yBACAjJ,EAAI4R,gBAAgBC,SACpB,OACA7R,EAAI4R,gBAAgBE,QAAQxK,qBAE7B8B,KAAMgN,EAAAA,OAIRtO,EAAAA,EAAAA,KAACqB,EAAAA,GAAQ,CAAAnB,UACRF,EAAAA,EAAAA,KAACqM,GAAoB,CACpB1S,kBAAmBzB,EAAIyB,kBACvBC,eAAgB1B,EAAI0B,eACpB0S,mBAAoBpU,EAAIoU,qBAAsB,QAMnDrK,cACC7D,IACCiC,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,CACEhI,EAAIiV,yBACJnN,EAAAA,EAAAA,KAACuO,EAAAA,GAAuB,CAAClL,IAAKnL,EAAIiV,yBAElCF,IAAkBD,IAClBhN,EAAAA,EAAAA,KAACwO,EAAAA,GAAiB,CAACxU,MAAO9B,EAAI8B,MAAOyU,UAAQ,KAE5CvR,IACD8C,EAAAA,EAAAA,KAACkC,EAAAA,EAAc,CACdC,cAAemL,EACfoB,iBAAe,EACf1U,MAAO9B,EAAI8B,MACXoI,YAAalK,EAAIiF,sBAMtBsG,QACClH,EAAaoS,cACZtO,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,CACE8M,IACAhN,EAAAA,EAAAA,KAAC4O,EAAAA,GAAa,CACb/K,SAAUC,EAAAA,GACV+K,WAAYC,EAAAA,GACZC,QAAS,CAAC7W,EAAI8B,OACdgV,cAAc,iBACd1M,MAAK,uBAAA1F,OAAuC,QAAvC6P,EAAyBvU,EAAI+R,kBAAU,IAAAwC,EAAAA,EAAIvU,EAAIE,SACpD6W,2BAA2B,qFAC3BC,eAAe,mCACf3F,aAAa,uHACb4F,kBAAiB,uBAAAvS,OAAuC,QAAvC8P,EAAyBxU,EAAI+R,kBAAU,IAAAyC,EAAAA,EAAIxU,EAAIE,SAChEgX,mBAAkB,8BAAAxS,OACH,QADG+P,EACjBzU,EAAI+R,kBAAU,IAAA0C,EAAAA,EAAIzU,EAAIE,QAAO,8FAE9BiX,cAAe7B,QAAcxW,KAI9BgJ,EAAAA,EAAAA,KAACsP,EAAAA,GAAqB,CACrB1L,eAAgBgK,EAChBvD,cAAenS,EAAImS,cACnBI,uBAAwBvS,EAAIuS,uBAC5BzQ,MAAO9B,EAAI8B,MACXxD,MAAOA,EACP+Y,UAAWzL,EAAAA,GACX0L,oBAAoB,sQAOxB,IGjKQC,GAAiCpT,IAG7C,MAAM,WAAEwJ,EAAU,aAAEtJ,EAAY,MAAE/F,EAAK,iBAAEkZ,GAAqBrT,GACvD5F,EAAYwP,IAAiBzI,EAAAA,EAAAA,UAAiB,IAC/C0I,GAAyB1H,EAAAA,EAAAA,cAAa2H,GAA0BF,EAAcE,IAAgB,IAC9F3J,GAAUqB,EAAAA,EAAAA,UAAQ,KAAMiJ,EAAAA,EAAAA,OAAc,IACtCC,EAAiBC,EAAAA,EAAOC,UAAUC,qBAElCtL,GAAWuL,EAAAA,EAAAA,eAEXC,EAAYgE,GAAwBxQ,GAAcA,EAAU9D,aAAaN,IAAQ,CAACA,IAElFmZ,EAAuBvE,GAC3BxQ,GAAcA,EAAUmQ,uBAAuB,CAAEvU,QAAOC,gBACzD,CAACD,EAAOC,IAEHmZ,EAAiBxE,GACrBxQ,GAAcA,EAAU4P,kBAAkB,CAAEhU,QAAOC,gBACpD,CAACD,EAAOC,IAGHoZ,EAAmBzE,GACvBxQ,GAAcA,EAAUqQ,oBAAoB,CAAEzU,QAAOC,gBACtD,CAACD,EAAOC,IAGHqZ,GAAmBtR,EAAAA,EAAAA,cACxB,CAACI,EAAUgJ,KACV,MAAOpR,GAASoR,EAAO7O,QFhCnB,SAA6B6C,EAAqBpF,EAAegB,GACvEoE,EAASuP,EAAsBrS,oBAAoB,CAAEtC,QAAOgB,SAC7D,CE+BGsB,CAAoB8C,EAAUpF,EAAOoI,EAASmR,eAAe,GAE9D,CAACnU,KAEKiM,EAAoBC,IAAY/I,EAAAA,EAAAA,UAASiR,GAAmBhI,EAAAA,GAAkB,CACpF/I,oBAAoB,EACpBE,YAAa,oBAIbC,UAAWA,CAACR,EAAUgJ,IAAWkI,EAAiBlR,EAAUgJ,MAG7DY,EAAAA,EAAAA,YAAU,KAGJpB,GACJU,EAAStR,GAGVkZ,EAAiB,iCAAiC,GAChD,CAACtI,EAAWU,EAAU4H,EAAkBlZ,IAI3C,MAAMiS,EAAe,CACpB,CACCC,QAAS,qBACTC,YAAagH,EAAqBlY,OAClCmR,SAAU,mEACVC,SACC7I,EAAAA,EAAAA,KAAC8I,EAAAA,GAAW,CACXC,iBAAiB,mBACjBhC,eAAiBlB,OAA8B7O,EAAjB+P,EAC9BlB,WAAYA,EAAW3F,SAEtByP,EAAqBpW,KAAKrB,IAC1B8H,EAAAA,EAAAA,KAACwM,GAAgB,CAChBtU,IAAKA,EAELqE,aAAcA,EACdC,QAASA,EACThG,MAAOA,EACPoF,SAAUA,GAJL1D,EAAI8B,YAUd,CACC0O,QAAS,cACTC,YAAaiH,EAAenY,OAC5BmR,SAAU,+EACVC,SACC7I,EAAAA,EAAAA,KAAC8I,EAAAA,GAAW,CACXC,iBAAiB,mBACjBhC,eAAiBlB,OAA8B7O,EAAjB+P,EAC9BlB,WAAYA,EAAW3F,SAEtB0P,EAAerW,KAAKrB,IACpB8H,EAAAA,EAAAA,KAACwM,GAAgB,CAChBtU,IAAKA,EAELqE,aAAcA,EACdC,QAASA,EACThG,MAAOA,EACPoF,SAAUA,GAJL1D,EAAI8B,YAUd,CACC0O,QAAS,eACTC,YAAakH,EAAiBpY,OAC9BmR,SAAU,mCACVC,SACC7I,EAAAA,EAAAA,KAAC8I,EAAAA,GAAW,CACXC,iBAAiB,mBACjBhC,eAAiBlB,OAA8B7O,EAAjB+P,EAC9BlB,WAAYA,EAAW3F,SAEtB2P,EAAiBtW,KAAKrB,IACtB8H,EAAAA,EAAAA,KAACwM,GAAgB,CAChBtU,IAAKA,EAELqE,aAAcA,EACdC,QAASA,EACThG,MAAOA,EACPoF,SAAUA,GAJL1D,EAAI8B,aAYf,OACCqG,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,CACE2F,IACA7F,EAAAA,EAAAA,KAACgJ,EAAAA,GAAW,CACXC,YAAY,uDACZC,iBAAkBhD,EAClBiD,gBAAiB,CAAEC,GAAI,WAGzBpJ,EAAAA,EAAAA,KAAC6H,EAAkB,CAClBwB,qBAAqBrJ,EAAAA,EAAAA,KAACsJ,EAAAA,GAAa,IACnCC,aAAa,qCACbC,yBAAuB,EAAAtJ,UAEvBF,EAAAA,EAAAA,KAAC4J,EAAAA,GAAa,CAACnB,KAAMA,QAEpB,EAILgH,GAAqBvF,WAAa,iBCvI3B,MAAM+F,IAAyB7T,EAAAA,EAAAA,OAAMC,IAC3C,MAAM,IAAEnE,EAAG,aAAEqE,EAAY,QAAEC,EAAO,MAAEhG,EAAK,iBAAE0Z,GAAqB7T,GAG1D,SAAEoB,IAAaC,EAAAA,EAAAA,KAAkB9C,GAAcA,EAAU+C,YAAY,IAErEiP,EAAc,GAAAhQ,OAAMa,EAASoP,YAAW,kBACxCC,EAAW,gBACX9P,EAAQ,GAAAJ,OAAMJ,EAAO,gBAAAI,OAAepG,EAAK,cAAAoG,OAAa1E,EAAIG,cAC1D4E,EAAU,GAAAL,OAAMJ,EAAO,qBAAAI,OAAoBpG,EAAK,cAAAoG,OAAa1E,EAAIG,cAEjE0U,GADa,GAAAnQ,OAAMJ,EAAO,cAAAI,OAAa1E,EAAI8B,OAC9B,GAAA4C,OAAMJ,EAAO,sCAG1BU,GAFc,GAAAN,OAAMJ,EAAO,cAAAI,OAAa1E,EAAI8B,MAAK,gBAE5B9B,EAAI8B,QAAU9B,EAAIiF,kBACvC8P,EAAgB/U,EAAIgV,wBAAwBzV,OAAS,EACrD2G,EACL6O,IACC/P,GACDhF,EAAIiV,wBACJjV,EAAIoG,qBACJpG,EAAImG,kBAEL,IAAI8R,EAAmB,GACnBjY,EAAIkY,wBACPD,EAAmB,8CACTjY,EAAImY,uBACdF,EAAmB,MAAQjY,EAAImY,sBAEhC,MAAMC,EAAiBpY,EAAImT,aAAY,eAAAzO,OACrBuT,EAAgB,QAAAvT,OAAO1E,EAAImT,aAAa7L,sBACvD,KAGG4N,GAFe,GAAAxQ,OAAM1E,EAAIqY,WAAU,2DAEhBrY,EAAImV,qBAAuBT,EAAiBE,GAAe5U,EAAI8B,OAClFsT,GACJpV,EAAIqV,kCAAoCX,EAAiBE,GAAe5U,EAAIiF,iBAI9E,OACC6C,EAAAA,EAAAA,KAAAC,EAAAA,SAAA,CAAAC,UACCF,EAAAA,EAAAA,KAACG,EAAAA,GAAY,CACZnG,MAAO9B,EAAI8B,MACX5B,QAASF,EAAIE,QACbgI,UAAUJ,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACgC,MAAM,yCAAwCpC,SAAEhI,EAAI+R,aACnE1J,QAAS6M,EACT5M,UAAU,0BACVC,kBACCJ,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,CACEhI,EAAI8V,mBACJhO,EAAAA,EAAAA,KAACiO,EAAAA,EAAK,CACLC,IAAKnB,EACLpL,EAAE,OACFV,EAAE,OACFqB,MAAM,qCACN,aAAW,oCACX6L,IAAI,iBACJ1L,QAAQ,iBAITwK,IAAiBjN,EAAAA,EAAAA,KAACoO,EAAAA,GAAiB,OAGtCxN,mBACCZ,EAAAA,EAAAA,KAACqO,EAAAA,GAAI,CAACvN,QAAQ,QAAQ2B,QAAQ,eAAcvC,UAC3CF,EAAAA,EAAAA,KAACqB,EAAAA,GAAQ,CAAAnB,UACRF,EAAAA,EAAAA,KAACgB,EAAAA,GAAS,CACTE,MAAM,OACNC,eAAgBmP,EAChBhP,KAAMiL,GAAAA,QAKViE,qBAEC,EAUDvO,cACC7D,IACCiC,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,CACEhI,EAAIiV,yBACJnN,EAAAA,EAAAA,KAACuO,EAAAA,GAAuB,CAAClL,IAAKnL,EAAIiV,yBAElCF,IACAjN,EAAAA,EAAAA,KAACwO,EAAAA,GAAiB,CAACxU,MAAO9B,EAAI8B,MAAOyU,UAAQ,KAE5CvR,IACD8C,EAAAA,EAAAA,KAACkC,EAAAA,EAAc,CACdlI,MAAO9B,EAAI8B,MACXoI,YAAalK,EAAIiF,iBACjBgF,cAAemL,IAGhBpV,EAAImG,oBACJgC,EAAAA,EAAAA,MAAC+C,EAAAA,EAAM,CACNC,IAAKrG,EACLsG,OAAO,SACPhB,MAAM,6CAA4CpC,SAAA,EAElDF,EAAAA,EAAAA,KAACuD,EAAAA,IAAW,CACXZ,MAAM,gBACNH,MAAO,CAAEC,QAAS,SAAUC,YAAa,SACxC,eAIHxK,EAAIoG,sBACJ+B,EAAAA,EAAAA,MAAC+C,EAAAA,EAAM,CACNC,IAAKpG,EACLqG,OAAO,SACPhB,MAAM,2DAA0DpC,SAAA,EAEhEF,EAAAA,EAAAA,KAACwD,EAAAA,IAAoB,CACpBb,MAAM,YACNH,MAAO,CAAEC,QAAS,SAAUC,YAAa,SACxC,wBAOPe,SAEC,KAwBA,IC1KQgN,GAA2BpU,IAGvC,MAAM,SAAEoB,IAAaC,EAAAA,EAAAA,KAAkB9C,GAAcA,EAAU+C,YAAY,KAErE,WAAEkI,EAAU,MAAErP,EAAK,iBAAEkZ,EAAgB,aAAEnT,GAAiBF,GACvD5F,EAAYwP,IAAiBzI,EAAAA,EAAAA,UAAiB,IAC/C0I,GAAyB1H,EAAAA,EAAAA,cAAa2H,GAA0BF,EAAcE,IAAgB,IAC9F3J,GAAUqB,EAAAA,EAAAA,UAAQ,KAAMiJ,EAAAA,EAAAA,OAAc,IACtCC,EAAiBC,EAAAA,EAAOC,UAAUC,qBAClCwJ,EAA6B1J,EAAAA,EAAOC,UAAU0J,2BAE9C/U,GAAWuL,EAAAA,EAAAA,eAEXC,EAAYgF,GAAkBxR,GAAcA,EAAU9D,aAAaN,IAAQ,CAACA,IAE5Eoa,EAAUxE,GAAkBxR,GAAcA,EAAU4Q,WAAW,CAAEhV,QAAOC,gBAAe,CAC5FD,EACAC,IAGKoa,EAA0BzE,GAC9BxR,GACAA,EAAU+Q,4BAA4B,CAAEnV,QAAOoV,UAAW8E,KAC3D,CAACla,IAGImR,GAA0BnJ,EAAAA,EAAAA,cAC/B,CAACI,EAAUgJ,KACV,MAAOpR,GAASoR,EAAO7O,QHlCnB,SAA6B6C,EAAqBpF,EAAegB,GACvEoE,EAASuQ,EAAgBrT,oBAAoB,CAAEtC,QAAOgB,SACvD,CGiCGsB,CAAoB8C,EAAUpF,EAAOoI,EAASkS,SAAS,GAExD,CAAClV,KAGKiM,EAAoBC,IAAY/I,EAAAA,EAAAA,UAASgS,GAAa/I,EAAAA,GAAkB,CAC9E/I,oBAAoB,EACpBE,YAAa,cAIbC,UAAWA,CAACR,EAAUgJ,IAAWD,EAAwB/I,EAAUgJ,MAGpEY,EAAAA,EAAAA,YAAU,KAMT,GAHKpB,GACJU,EAAStR,QAEsBQ,IAA5B6Z,EAAuC,CAC1C,MAAMzQ,EAAQ,GAAAxD,OAAMiU,EAAuB,sBAAAjU,OAAqB8T,EAA0B,WAC1FhB,EAAiBtP,EAClB,IACE,CAACgH,EAAWU,EAAUtR,EAAOqa,EAAyBnB,EAAkBgB,IAI3E,MAAMjI,EAAe,CACpB,CACCC,QAAS,YACTC,YAAaiI,EAAQnZ,OACrBmR,SAAS,YAADhM,OAAcoK,EAAAA,EAAOgK,SAAQ,SACrCnI,SACC7I,EAAAA,EAAAA,KAAC8I,EAAAA,GAAW,CACXC,iBAAiB,mBACjBhC,eAAiBlB,OAA8B7O,EAAjB+P,EAC9BlB,WAAYA,EAAW3F,SAEtB0Q,EAAQrX,KAAKrB,IACb8H,EAAAA,EAAAA,KAACiQ,GAAU,CACV/X,IAAKA,EAEL1B,MAAOA,EACPgG,QAASA,EACTD,aAAcA,EACd2T,iBAAkBzS,EAASyS,kBAJtBhY,EAAI8B,aAYf,OACCqG,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,CACE2F,IACA7F,EAAAA,EAAAA,KAACgJ,EAAAA,GAAW,CACXC,YAAY,uDACZC,iBAAkBhD,EAClBiD,gBAAiB,CAAEC,GAAI,WAGzBpJ,EAAAA,EAAAA,KAAC6H,EAAkB,CAClBwB,qBAAqBrJ,EAAAA,EAAAA,KAACsJ,EAAAA,GAAa,IACnCC,aAAa,qCACbC,yBAAuB,EAAAtJ,UAEvBF,EAAAA,EAAAA,KAAC4J,EAAAA,GAAa,CAACnB,KAAMA,QAEpB,EAILgI,GAAevG,WAAa,W,0ECxErB,MAAM+G,IAA6C7U,EAAAA,EAAAA,OAAMC,IAC/D,MAAM,IACLnE,EAAG,aACHqE,EAAY,eACZqQ,EAAc,YACdE,EAAW,cACXC,EAAa,MACbvW,EAAK,mBACL0a,EAAkB,SAClBtV,EAAQ,eACRuV,EAAc,SACdC,EAAQ,iBACRlB,GACG7T,GAIGmR,EAAYC,IAAiBjQ,EAAAA,EAAAA,UAAoD,OACjF6T,EAAkBC,IAAuB9T,EAAAA,EAAAA,WAAkB,IAC3D+T,EAAkBC,IAAuBhU,EAAAA,EAAAA,UAA0BoH,EAAAA,GAAgBC,SAEpF4M,EACLF,IAAqB3M,EAAAA,GAAgBC,QAAU,2BAA6B,qBAEvE6M,EACLH,IAAqB3M,EAAAA,GAAgBC,QAAU3M,EAAIyZ,yBAA2BzZ,EAAI0Z,mBAE7EC,EAlDP,SAA6BC,EAAmBC,GAC/C,GAAID,EAAYC,EAAa,CAC5B,MAAMC,EAAeF,EAAYC,EACjC,MAAM,OAANnV,OAAcoV,EAAY,uBAAApV,OAAuC,IAAjBoV,EAAqB,IAAM,GAC5E,CACA,OAAO,IACR,CA4C0BC,CADPV,IAAqB3M,EAAAA,GAAgBC,QAAU3M,EAAIga,kBAAoBha,EAAIia,YACrCT,EAAYja,QAE9D2a,EAAwBla,EAAIyZ,yBAAyBla,OAAS,EAC9D4a,EAAkBna,EAAI0Z,mBAAmBna,OAAS,EAElD6a,GAAsB9T,EAAAA,EAAAA,cAC1BmG,GAA6B,KAC7B6M,EAAoB7M,GACpB2M,GAAoB,EAAK,GAE1B,IAEKiB,GAAwB/T,EAAAA,EAAAA,cAC5BgU,GAAkB,KAClBlB,EAAoBkB,EAAK,GAE1B,IAGK9E,GAAsBlP,EAAAA,EAAAA,cAC1BmP,GAAuDF,EAAcE,IACtE,IAGK8E,EAAsB,GAAA7V,OAAM1E,EAAIga,kBAAiB,iBAAAtV,OAC5B,IAA1B1E,EAAIga,kBAA0B,MAAQ,QAAO,yBAAAtV,OACtBwV,EAAwB,qBAAuB,IAEjEM,EAAgB,GAAA9V,OAAM1E,EAAIia,YAAW,iBAAAvV,OACtB,IAApB1E,EAAIia,YAAoB,MAAQ,QAAO,sBAAAvV,OACnByV,EAAkB,qBAAuB,IAKxDjF,GAHc,GAAAxQ,OAAMgQ,GAAchQ,OAAG1E,EAAI8B,MAAK,gBAC/B,GAAA4C,OAAM1E,EAAIqY,WAAU,2DAEhBrY,EAAImV,qBAAuBT,EAAiBE,GAAe5U,EAAI8B,OAGxF,OACCqG,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,EACCF,EAAAA,EAAAA,KAACG,EAAAA,GAAY,CACZnG,MAAO9B,EAAI8B,MACX5B,QAASF,EAAIE,QACbgI,UAAUJ,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACgC,MAAM,yCAAwCpC,SAAEhI,EAAI+R,aACnE1J,QAAS6M,EACTW,iBAAkBL,EAClBlN,UAAU,0BACVC,kBACCJ,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,CACEhI,EAAI8V,mBACJhO,EAAAA,EAAAA,KAACiO,EAAAA,EAAK,CACLC,IAAKnB,EACLpL,EAAE,OACFV,EAAE,OACFqB,MAAM,qCACN,aAAW,oCACX6L,IAAI,iBACJ1L,QAAQ,iBAGTvK,EAAIya,uBAAwB3S,EAAAA,EAAAA,KAACoO,EAAAA,GAAiB,OAGjDxN,mBACCP,EAAAA,EAAAA,MAACQ,EAAAA,GAAM,CAACC,QAAQ,QAAQC,MAAM,cAAab,SAAA,EAC1CF,EAAAA,EAAAA,KAAC4S,GAAc,CACd3R,EAAE,OACF4R,mBAAoB3a,EAAI8B,MACxB8Y,YAAa5a,EAAI4a,YACjBvW,aAAcA,IAEdrE,EAAI6a,iBACJ/S,EAAAA,EAAAA,KAACgT,GAAAA,EAAsB,CACtBH,mBAAoB3a,EAAI8B,MACxB+Y,eAAgB7a,EAAI6a,eACpBxW,aAAcA,OAKlB0F,cACC/J,EAAIiV,yBAA0BnN,EAAAA,EAAAA,KAACuO,EAAAA,GAAuB,CAAClL,IAAKnL,EAAIiV,yBAEjE1J,QACClH,EAAaoS,aACbuC,IACClR,EAAAA,EAAAA,KAACiT,GAAoB,CACpB/a,IAAKA,EACL1B,MAAOA,EACPoF,SAAUA,EACV4R,WAAYA,EACZJ,gBAAiBA,EACjB8C,iBAAkBA,IAIrBM,qBACCnQ,EAAAA,EAAAA,MAAC6S,GAAAA,EAAI,CAACpS,QAAQ,SAAQZ,SAAA,CACpBgQ,IACA7P,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,EACCF,EAAAA,EAAAA,KAACmT,GAAAA,EAAQ,CAAAjT,UACRF,EAAAA,EAAAA,KAACoT,EAAAA,GAAc,CACdC,SAAUjB,EACVkB,YAAa,CACZC,QAASnB,EACNE,EAAoB1N,EAAAA,GAAgBC,cACpC7N,GAEJsL,MAAOmQ,EACPe,MAAOtb,EAAIga,kBAAkBuB,WAC7BC,iBAAe,EAAAxT,UAEfF,EAAAA,EAAAA,KAACiO,EAAAA,EAAK,CAACC,IAAKiD,EAAgBxP,EAAE,OAAOV,EAAE,OAAOwB,QAAQ,gBAGxDzC,EAAAA,EAAAA,KAACmT,GAAAA,EAAQ,CAAAjT,UACRF,EAAAA,EAAAA,KAACoT,EAAAA,GAAc,CACdC,SAAUhB,EACViB,YAAa,CACZC,QAASlB,EACNC,EAAoB1N,EAAAA,GAAgBS,WACpCrO,GAEJsL,MAAOoQ,EACPc,MAAOtb,EAAIia,YAAYsB,WACvBC,iBAAe,EAAAxT,UAEfF,EAAAA,EAAAA,KAACiO,EAAAA,EAAK,CAACC,IAAKkD,EAAUzP,EAAE,OAAOV,EAAE,OAAOwB,QAAQ,mBAQnD,QAoBJpC,EAAAA,EAAAA,MAACsT,GAAAA,GAAK,CAACC,OAAQvC,EAAkBwC,QAAStB,GAAsB,GAAOrS,SAAA,EACtEF,EAAAA,EAAAA,KAAC8T,GAAAA,GAAY,KACbzT,EAAAA,EAAAA,MAAC0T,GAAAA,GAAY,CAAA7T,SAAA,EACZF,EAAAA,EAAAA,KAACgU,GAAAA,GAAW,CAAA9T,SAAEuR,KACdzR,EAAAA,EAAAA,KAACiU,GAAAA,GAAgB,KACjB5T,EAAAA,EAAAA,MAAC6T,GAAAA,GAAS,CAACC,GAAI,EAAEjU,SAAA,CACfwR,EAAYnY,KAAI,CAAC6a,EAASC,KAC1BrU,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAAagU,WAAW,OAAOjM,GAAG,QAAOnI,SAC3CkU,GADQC,KAIVxC,IAAoB7R,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAAC+H,GAAG,QAAOnI,SAAE2R,QAEvC7R,EAAAA,EAAAA,KAACuU,GAAAA,GAAW,CAAArU,UACXF,EAAAA,EAAAA,KAACwU,GAAAA,EAAM,CAACC,YAAY,OAAOlB,QAAShB,GAAsB,GAAOrS,SAAC,iBAMnE,ICzOQ+S,IAAuD7W,EAAAA,EAAAA,OAClEC,IAAuC,IAADoQ,EAAAC,EACtC,MAAM,IAAExU,EAAG,SAAE0D,EAAQ,MAAEpF,EAAK,WAAEgX,EAAU,gBAAEJ,EAAe,iBAAE8C,GAAqB7T,EAEhF,OACCgE,EAAAA,EAAAA,MAACQ,EAAAA,GAAM,CAACI,EAAE,OAAOH,QAAQ,SAAQZ,SAAA,EAChCF,EAAAA,EAAAA,KAAC8D,EAAAA,GAAkB,CAClB2Q,YAAY,QACZC,UAAU1U,EAAAA,EAAAA,KAAC2U,EAAAA,IAAa,CAAChU,KAAM,KAC/B0C,IAAK+J,EACL9J,OAAO,QACPhB,MAAM,0BACNoH,GAAItG,EAAAA,EACJwR,eAAe,OACfC,OAAQ,CACPD,eAAgB,OAChBE,WAAY,WACZnS,MAAO,SACNzC,SACF,aAGAgQ,IACAlQ,EAAAA,EAAAA,KAAC4O,EAAAA,GAAa,CACb/K,SAAUC,EAAAA,GACV+K,WAAYkG,EAAAA,GACZhG,QAAS,CAAC7W,EAAI8B,OACdgV,cAAc,UACdK,cAAe7B,QAAcxW,EAC7BsL,MAAK,OAAA1F,OAAS1E,EAAI+R,WAAU,+BAAArN,OAA8B1E,EAAIE,SAC9D6W,2BAA2B,2GAC3BC,eAAe,mCACf3F,aAAa,uHACb4F,kBAAiB,WAAAvS,OAA2B,QAA3B6P,EAAavU,EAAI+R,kBAAU,IAAAwC,EAAAA,EAAIvU,EAAIE,SACpDgX,mBAAkB,8BAAAxS,OACH,QADG8P,EACjBxU,EAAI+R,kBAAU,IAAAyC,EAAAA,EAAIxU,EAAIE,QAAO,uHAIhC4H,EAAAA,EAAAA,KAACgV,GAAAA,EAA4B,CAAC9c,IAAKA,EAAK1B,MAAOA,EAAOoF,SAAUA,MACxD,ICzCCgX,IAA4BxW,EAAAA,EAAAA,OAAMC,IAC9C,MAAM,YAAEyW,EAAW,aAAEvW,EAAY,mBAAEsW,KAAuBoC,GAAS5Y,EAC7D6Y,GACJ3Y,EAAaoS,aAAepS,EAAa+L,aAAewK,EAAYqC,MAAMC,GAAMA,EAAErL,WAEpF,GAA2B,IAAvB+I,EAAYrb,OACf,OAAO,KAGR,MAAM4d,EAAqBH,EAExBpC,EAAYvZ,KAAI,CAAC+b,EAAKjB,KACtB,MAAMkB,EAAiB1C,IAAuByC,EAAIE,aAClD,OACCnV,EAAAA,EAAAA,MAACC,EAAAA,GAAG,CAAakB,GAAc,IAAV6S,EAAc,GAAK,QAAQnU,SAAA,CAC9CoV,EAAIvL,SAAW,aAAa,OAAKuL,EAAItL,QAAQxK,qBAAsB,IACnE+V,IACAvV,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACoJ,GAAG,OAAO+L,UAAU,SAASC,SAAS,QAAOxV,SAAC,6BAH3CmU,EAOJ,IAXP,KAeH,OACCrU,EAAAA,EAAAA,KAAAC,EAAAA,SAAA,CAAAC,UACCF,EAAAA,EAAAA,KAACgB,EAAAA,GAAS,CACTE,MAAO4R,EAAYrb,OAAS,eAAwC,IAAvBqb,EAAYrb,OAAe,GAAK,KAC7E0J,eAAgBkU,EAChB/T,KAAMgN,EAAAA,EACNzM,aAAc,CAAEZ,EAAG,QAASe,KAAM,YAC9BiT,KAEH,I,gBClCE,MAAMU,GAAgCtZ,IAE5C,MAAM,WAAEwJ,EAAU,aAAEtJ,EAAY,MAAE/F,GAAU6F,GACrC5F,EAAYwP,IAAiBzI,EAAAA,EAAAA,UAAiB,IAC/C0I,GAAyB1H,EAAAA,EAAAA,cAAa2H,GAA0BF,EAAcE,IAAgB,KAC9F,SAAE1I,IAAaC,EAAAA,EAAAA,KAAkB9C,GAAcA,EAAU+C,YAAY,IAErEnB,GAAUqB,EAAAA,EAAAA,UAAQ,KAAMiJ,EAAAA,EAAAA,OAAc,IACtC8F,EAAc,GAAAhQ,OAAMa,EAASoP,YAAW,kBACxCC,EAAW,gBACXqE,EAAc,GAAAvU,OAAMJ,EAAO,2DAC3B4U,EAAQ,GAAAxU,OAAMJ,EAAO,qDACrBuQ,EAAa,GAAAnQ,OAAMJ,EAAO,qCAC1BuK,EAAiBC,EAAAA,EAAOC,UAAUC,qBAElCtL,GAAWuL,EAAAA,EAAAA,eACXC,GAAYwO,EAAAA,GAAAA,KAAuBhb,GAAcA,EAAU9D,aAAaN,IAAQ,CAACA,KAChF0a,IAAsB0E,EAAAA,GAAAA,KAC3Bhb,GAAcA,EAAUib,oBAAoBrf,IAC7C,IAGKsf,GAAkBF,EAAAA,GAAAA,KACtBhb,GAAcA,EAAUmb,mBAAmB,CAAEvf,QAAOC,gBACrD,CAACD,EAAOC,IAEHuf,GAAaJ,EAAAA,GAAAA,KACjBhb,GAAcA,EAAUqb,0BAA0B,CAAEzf,QAAOC,gBAC5D,CAACD,EAAOC,IAGHyf,GAA4B1X,EAAAA,EAAAA,cACjC,CAACI,EAAUgJ,KACV,MAAOpR,GAASoR,EAAO7O,QACvBod,EAAAA,GAAAA,IACCva,EACApF,EACAoI,EAASwX,cACTxX,EAASsS,mBACTtS,EAASyX,sBACTzX,EAAS0X,gCACT1X,EAAS2X,oCACT,GAEF,CAAC3a,KAEKiM,EAAoB2O,IAAqBzX,EAAAA,EAAAA,UAAS0X,GAAkBzO,EAAAA,GAAkB,CAC5F/I,oBAAoB,EACpBE,YAAa,mBAIbC,UAAWA,CAACR,EAAUgJ,IAAWsO,EAA0BtX,EAAUgJ,MAGtEY,EAAAA,EAAAA,YAAU,KAGJpB,GACJoP,EAAkBhgB,EACnB,GACE,CAAC4Q,EAAWoP,EAAmBhgB,IAIlC,MAAMiS,EAAe,CACpB,CACCC,QAAS,eACTC,YAAamN,EAAgBre,OAC7BmR,SAAU,kCACVC,SACC7I,EAAAA,EAAAA,KAAC8I,EAAAA,GAAW,CACXC,iBAAiB,mBACjBhC,eAAiBlB,OAA8B7O,EAAjB+P,EAC9BlB,WAAYA,EAAW3F,SAEtB4V,EAAgBvc,KAAK5B,IACrBqI,EAAAA,EAAAA,KAACiR,GAAe,CAEf/Y,IAAKP,EACL4E,aAAcA,EACdqQ,eAAgBA,EAChBE,YAAaA,EACbC,cAAeA,EACfmE,mBAAoBA,EACpB1a,MAAOA,EACPoF,SAAUA,EACVuV,eAAgBA,EAChBC,SAAUA,EACVlB,iBAAkBzS,EAASyS,kBAXtBvY,EAAEqC,YAiBZ,CACC0O,QAAS,UACTC,YAAaqN,EAAWve,OACxBmR,SAAU,+DACVC,SACC7I,EAAAA,EAAAA,KAAC8I,EAAAA,GAAW,CACXC,iBAAiB,mBACjBhC,eAAiBlB,OAA8B7O,EAAjB+P,EAC9BlB,WAAYA,EAAW3F,SAEtB8V,EAAWzc,KAAK5B,IAChBqI,EAAAA,EAAAA,KAACiR,GAAe,CAEf/Y,IAAKP,EACL4E,aAAcA,EACdqQ,eAAgBA,EAChBE,YAAaA,EACbC,cAAeA,EACfmE,mBAAoBA,EACpB1a,MAAOA,EACPoF,SAAUA,EACVuV,eAAgBA,EAChBC,SAAUA,EACVlB,iBAAkBzS,EAASyS,kBAXtBvY,EAAEqC,aAmBb,OACCqG,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,CACE2F,IACA7F,EAAAA,EAAAA,KAACgJ,EAAAA,GAAW,CACXC,YAAY,uDACZC,iBAAkBhD,EAClBiD,gBAAiB,CAAEC,GAAI,QACvB,iBAGFpJ,EAAAA,EAAAA,KAAC6H,EAAkB,CAClBwB,qBAAqBrJ,EAAAA,EAAAA,KAACsJ,EAAAA,GAAa,IACnCC,aAAa,qCACbC,yBAAuB,EAAAtJ,UAEvBF,EAAAA,EAAAA,KAAC4J,EAAAA,GAAa,CAACnB,KAAMA,QAEpB,EC1IEiO,eAAeC,KAErB,aADyCC,EAAAA,EAAI1f,IAA0B,+BAExE,CAQOwf,eAAeG,GACrBC,EACAC,GAMA,aAJiDH,EAAAA,EAAII,KACpD,mCACA,CAAEC,WAAYH,EAAqBI,kBAAmBH,GAGxD,CAOOL,eAAeS,GACrBL,GAMA,aAJsDF,EAAAA,EAAII,KACzD,8BACA,CAAEC,WAAYH,GAGhB,CAQOJ,eAAeD,GAAiBjgB,GAItC,aAH0DogB,EAAAA,EAAI1f,IAAG,0CAAA0F,OACtBpG,GAG5C,CAWOkgB,eAAeU,GACrBpd,EACAqd,EACAC,EACAC,EACAC,EACAC,GAYA,aAVuBb,EAAAA,EAAII,KAC1B,8CACA,CACCU,MAAO1d,EACP2d,cAAeL,EACfM,aAAcL,EACdM,sBAAuBL,EACvBM,QAASL,GAIZ,CAOOf,eAAe1G,GAAkBxZ,GAIvC,aAH2DogB,EAAAA,EAAI1f,IAAG,2CAAA0F,OACtBpG,GAG7C,CAOOkgB,eAAe3F,GAAYva,GAIjC,aAHqDogB,EAAAA,EAAI1f,IAAG,qCAAA0F,OACtBpG,GAGvC,CAOOkgB,eAAe3O,GAAiBvR,GAItC,aAH0DogB,EAAAA,EAAI1f,IAAG,0CAAA0F,OACtBpG,GAG5C,CAOOkgB,eAAe3R,GACrBgT,GAOA,aALwDnB,EAAAA,EAAII,KAC3D,mDACAe,EAIF,CAOOrB,eAAe1X,GAAehF,GAIpC,aAHqD4c,EAAAA,EAAI1f,IAAG,4CAAA0F,OACf5C,GAG9C,CAMO,SAASge,KAQf,OAP6C,IAAI7e,IAAI,CAEpD,CAACwc,GAAoBzL,WAAYyL,IACjC,CAAClG,GAAqBvF,WAAYuF,IAClC,CAACgB,GAAevG,WAAYuG,IAC5B,CAAC7K,EAAoBsE,WAAYtE,IAGnC,CDfA+P,GAAoBzL,WAAa,e,kKE9J1B,MAAMpG,EAA8DzH,IAC1E,MAAM,SAAEqY,EAAQ,SAAExU,KAAa+U,GAAS5Y,EAExC,OACC2D,EAAAA,EAAAA,KAACwU,EAAAA,EAAM,IACFS,EACJgD,QAAQ,UACRtX,KAAK,KACLM,EAAE,OACFiX,WAAW,SACXvW,EAAE,QACFwW,KAAK,IACL1V,QAAQ,QACR0R,GAAG,QACHiE,GAAG,QAAOlY,UAEVG,EAAAA,EAAAA,MAACgY,EAAAA,EAAU,CAACC,QAAS,GAAGpY,SAAA,EACvBF,EAAAA,EAAAA,KAACuY,EAAAA,EAAQ,CAACC,QAAS,CAAE1W,KAAM,EAAGC,GAAI,GAAI7B,UACrCF,EAAAA,EAAAA,KAACyY,EAAAA,EAAI,CAACC,QAAQ,aAAYxY,SAAEwU,OAE7B1U,EAAAA,EAAAA,KAACuY,EAAAA,EAAQ,CAACC,QAAS,CAAE1W,KAAM,GAAIC,GAAI,IAAMsG,GAAI,CAAEvG,KAAM,QAASC,GAAI,UAAW7B,UAC5EF,EAAAA,EAAAA,KAACyY,EAAAA,EAAI,CAACC,QAAQ,aAAa/W,EAAE,OAAMzB,UAClCF,EAAAA,EAAAA,KAAC2Y,EAAAA,EAAM,CAAAzY,SAAEA,YAIJ,E,yBCdJ,MAAMkT,GAA6BhX,EAAAA,EAAAA,OAAMC,IAC/C,MAAM,MAAEiG,EAAK,MAAEkR,EAAK,gBAAEE,EAAe,SAAExT,EAAQ,SAAEmT,EAAQ,YAAEC,GAAgBjX,EACrEuc,EAAS,OACTC,EAAW,OACXhQ,GACLxI,EAAAA,EAAAA,MAACsY,EAAAA,EAAM,CACNhX,EAAGiX,EACHE,KAAMD,EACNpW,QAAQ,eACRsW,GAAG,UACHC,EAAE,MACFrW,MAAM,UACNsW,aAAa,MACb3W,MAAQoR,EAA0B,GAARpR,EAAWpC,SAAA,CAEpCsT,IACAxT,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACoV,SAAS,QAAQpB,WAAW,OAAO5K,GAAG,OAAMxJ,SAC/CsT,IAGFtT,KAGH,OAAOwT,GACN1T,EAAAA,EAAAA,KAACkZ,EAAAA,GAAS,CACTtQ,SAAUtG,EACV+Q,SAAUA,EACVC,YAAa,IAAKA,EAAa3R,EAAGiX,EAAQE,KAAMD,GAAW3Y,SAE1D2I,KAGF7I,EAAAA,EAAAA,KAAAC,EAAAA,SAAA,CAAAC,SAAG2I,GACH,I,sGCNK,MAAM1I,GAAuC/D,EAAAA,EAAAA,OAAMC,IACzD,MAAM,MACLrC,EAAK,QACL5B,EAAO,SACPgI,EAAQ,QACRqD,EAAO,QACPlD,EAAO,cACP0B,EAAa,UACbzB,EAAS,kBACTI,EAAiB,oBACjB4P,EAAmB,iBACnB/P,EAAgB,iBAChBsN,GACG1R,EACEG,GAAUqB,EAAAA,EAAAA,UAAQ,KAAMiJ,EAAAA,EAAAA,OAAc,IACtCqS,EAAY,GAAAvc,OAAMJ,EAAO,4BAAAI,OAA2B5C,GACpDof,EAAoB,GAAAxc,OAAMJ,EAAO,sCACjC6c,EAAiB,0BAA6Brf,EAAQgN,EAAAA,EAAOsS,sBAC7DC,GAAWC,EAAAA,EAAAA,GAAmB,CAAE1X,MAAM,EAAMC,IAAI,IAChD4L,GAAU8L,EAAAA,EAAAA,QAA0B,MAI1C,OAFAjR,EAAAA,EAAAA,YAAU,IAAMuF,GAAoBA,EAAiBJ,IAAU,CAACI,KAG/D/N,EAAAA,EAAAA,KAACqB,EAAAA,GAAQ,CAAAnB,UACRG,EAAAA,EAAAA,MAACgY,EAAAA,EAAU,CACVC,QAAS,GACTU,EAAE,QACFC,aAAa,MACbS,gBAAgB,QAChBC,EAAE,QACFC,OAAO,sBAAqB1Z,SAAA,EAE5BG,EAAAA,EAAAA,MAACkY,EAAAA,EAAQ,CAACC,QAAS,CAAE1W,KAAM,EAAGC,GAAI,GAAI7B,SAAA,EAErCF,EAAAA,EAAAA,KAAC2Y,EAAAA,EAAM,CAAAzY,UACNF,EAAAA,EAAAA,KAAC6Z,EAAAA,EAAW,CAAC7X,KAAK,OAAO8X,MAAO,EAAGC,KAAK,WAAU7Z,UACjDF,EAAAA,EAAAA,KAACiO,EAAAA,EAAK,CACLC,IAAKiL,EACLa,YAAaZ,EACbjL,IAAI,WACJ2G,WAAYuE,SAIdY,EAAAA,EAAAA,IAAwBxZ,KACxBT,EAAAA,EAAAA,KAAC2Y,EAAAA,EAAM,CAAAzY,UACNF,EAAAA,EAAAA,KAACka,EAAAA,GAAM,CAACpZ,QAAQ,QAAQU,GAAG,SAAQtB,SACjCO,UAKLJ,EAAAA,EAAAA,MAACkY,EAAAA,EAAQ,CAACC,QAAS,CAAE1W,KAAM,EAAGC,GAAI,GAAKsG,GAAG,SAASsB,GAAG,QAAOzJ,SAAA,CAG3DK,GACAP,EAAAA,EAAAA,KAACoD,EAAAA,EAAM,CACN+W,IAAKxM,EACLsK,QAAQ,QACR5U,IAAK9C,EACL+B,MAAO9B,EACP8C,OAAO,SACPgR,WAAW,OAAMpU,SAEhB9H,KAGF4H,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACgU,WAAW,OAAMpU,SAAE9H,IAExBgI,IAAYJ,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAAAJ,SAAEE,IAClBqD,GAAW8V,GACXvZ,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACkB,GAAG,QAAQ4Y,UAAU,OAAMla,SAC9BU,IAEC,SAELZ,EAAAA,EAAAA,KAACuY,EAAAA,EAAQ,CACRC,QAAS,CAAE1W,KAAM,GAAIC,GAAI,GACzBsG,GAAI,CAAEvG,KAAM,EAAGC,GAAI,UACnBP,GAAI,CAAEM,KAAM,QAASC,GAAI,GAAI7B,UAE7BG,EAAAA,EAAAA,MAACoY,EAAAA,EAAI,CAACC,QAAQ,aAAYxY,SAAA,CAAC,IAAEsQ,QAE9BxQ,EAAAA,EAAAA,KAACuY,EAAAA,EAAQ,CAACC,QAAS,CAAE1W,KAAM,GAAIC,GAAI,GAAKP,GAAI,CAAEM,KAAM,QAASC,GAAI,GAAI7B,SAEnEuD,GACAzD,EAAAA,EAAAA,KAACyY,EAAAA,EAAI,CAACC,QAAS,CAAE5W,KAAM,aAAcC,GAAI,YAAc4H,GAAG,QAAOzJ,SAC/DuD,IAEE8V,EAID,MAHHvZ,EAAAA,EAAAA,KAACyY,EAAAA,EAAI,CAACC,QAAQ,WAAW/O,GAAG,QAAQyQ,UAAU,QAAOla,SACnDU,OAIHqZ,EAAAA,EAAAA,IAAwBhY,KACxB5B,EAAAA,EAAAA,MAACkY,EAAAA,EAAQ,CAACC,QAAS,GAAIhX,GAAI,CAAEM,KAAM,QAASC,GAAI,GAAI7B,SAAA,EACnDF,EAAAA,EAAAA,KAACqa,EAAAA,EAAO,CAACV,EAAE,aACX3Z,EAAAA,EAAAA,KAACka,EAAAA,GAAM,CAACpZ,QAAQ,MAAKZ,SAAE+B,WAIhB,I,wBC/IN,MAAMqH,EAAoBA,KAE/BtJ,EAAAA,EAAAA,KAACsa,EAAAA,EAAO,CAACC,KAAK,SAASC,YAAY,MAAM/X,QAAQ,QAAQkX,EAAE,sBAAsB1Y,EAAE,OAAOU,EAAE,OAAMzB,UACjGF,EAAAA,EAAAA,KAACya,EAAAA,GAAc,CAAAva,SAAC,cCQN4I,GAAqC1M,EAAAA,EAAAA,OAAMC,IACvD,MAAM,iBAAE0M,EAAgB,SAAE7I,EAAQ,eAAE6G,EAAc,WAAElB,GAAexJ,EAC7Dqe,EAAuB3T,GAAkB,EACzC4T,GAAiBnB,EAAAA,EAAAA,GAAmB,CAAE1X,KAAM,OAAQ8Y,GAAI,OAAQ,MAAO,OAAQ,MAAO,SAE5F,OAAuC,IAAnCC,EAAAA,SAAeC,MAAM5a,IAEvBF,EAAAA,EAAAA,KAAC2Y,EAAAA,EAAM,CACNlD,UAAU,SACV9T,EAAGkE,EAAa,OAAS,QACzB6P,SAAU7P,EAAa,SAAW,SAAS3F,SAE1C6I,KAMH/I,EAAAA,EAAAA,KAACqO,EAAAA,GAAI,CAAAnO,SACH6G,GACA/G,EAAAA,EAAAA,KAAC+a,EAAAA,GAAa,CAAChU,eAAgB2T,EAAsB/Y,EAAE,SAAQzB,SAC7DA,KAGFF,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACqB,EAAGkE,EAAa8U,EAAiB,QAASK,UAAU,SAAQ9a,SAC/DA,KAGG,I,aCjBF,MAAMc,GAAuB5E,EAAAA,EAAAA,OAAMC,IACzC,MAAM,eACL8E,EAAc,MACdD,EAAK,KACLI,EAAI,UACJI,EAAS,aACTG,EAAY,UACZoZ,EAAS,eACTC,KACGjG,GACA5Y,EACE8e,GACL9a,EAAAA,EAAAA,MAAC+a,EAAAA,GAAG,IAAKnG,EAAMtS,MAAM,qBAAqBmS,WAAW,qBAAoB5U,SAAA,CACvEoB,IAAQtB,EAAAA,EAAAA,KAACqb,EAAAA,GAAW,CAAC3R,GAAIpI,KAAUI,KACpC1B,EAAAA,EAAAA,KAACsb,EAAAA,GAAQ,CAAApb,SAAEgB,IACV+Z,IAAajb,EAAAA,EAAAA,KAACub,EAAAA,GAAY,CAAC7R,GAAIuR,KAAeC,OAGjD,OAAO/Z,GACNnB,EAAAA,EAAAA,KAACkZ,EAAAA,GAAS,CACTtQ,SAAUzH,KACNU,EACJ2Z,SAAU,CAAE/Y,QAAS,SAAU1B,MAAO,QAASb,SAE9Cib,IAGFA,CACA,G,oRCDK,MAAMnG,GAA0C5Y,EAAAA,EAAAA,OAAMC,IAAkB,IAADof,EAAAC,EAC7E,MAAM,IACLxjB,EAAG,SACH0D,EAAQ,MACRpF,EAAK,eACLoN,EAAc,eACd+X,EAAc,gBACdC,EAAe,SACf/X,EAAQ,WACRgY,EAAU,YACVC,EAAW,UACXC,KACG9G,GACA5Y,EAGE2f,EAA+C,OAApB,OAAH9jB,QAAG,IAAHA,OAAG,EAAHA,EAAK6a,gBAC7BkJ,EACJL,GAAmBA,EAAkB,GAA2B,OAAjB,OAAH1jB,QAAG,IAAHA,OAAG,EAAHA,EAAK4a,eAA0B,OAAH5a,QAAG,IAAHA,OAAG,EAAHA,EAAK4a,YAAYrb,QAAS,EAC9FykB,EAAoB,gJAAAtf,OACzBqf,EAAiB,8CAAgD,GAAE,MAG9D,OAAErI,EAAM,OAAEuI,EAAM,QAAEtI,IAAYuI,EAAAA,EAAAA,MAC7B9E,EAAe+E,IAAoB7e,EAAAA,EAAAA,UAAS,KAC5C+Z,EAAc+E,IAAmB9e,EAAAA,EAAAA,UAAS,KAC1Cga,EAAuB+E,IAA4B/e,EAAAA,EAAAA,WAAS,IAC5Dgf,EAAwBC,IAA6Bjf,EAAAA,EAAAA,WAAkB,GAExEkf,GAA4Ble,EAAAA,EAAAA,cAChCgU,GAAkB,IAAMiK,EAA0BjK,IACnD,IAIKmK,GAAane,EAAAA,EAAAA,cAAY,KAAO,IAADoe,EAAAC,EACpCR,GAAoB,OAAHnkB,QAAG,IAAHA,GAAmB,QAAhB0kB,EAAH1kB,EAAK6a,sBAAc,IAAA6J,OAAhB,EAAHA,EAAqBtF,gBAAiB,IACvDgF,GAAmB,OAAHpkB,QAAG,IAAHA,GAAmB,QAAhB2kB,EAAH3kB,EAAK6a,sBAAc,IAAA8J,OAAhB,EAAHA,EAAqBtF,eAAgB,IACrDgF,GAAyB,GACzBJ,GAAQ,GACN,CAAI,OAAHjkB,QAAG,IAAHA,GAAmB,QAAhBujB,EAAHvjB,EAAK6a,sBAAc,IAAA0I,OAAhB,EAAHA,EAAqBnE,cAAkB,OAAHpf,QAAG,IAAHA,GAAmB,QAAhBwjB,EAAHxjB,EAAK6a,sBAAc,IAAA2I,OAAhB,EAAHA,EAAqBnE,aAAc4E,IAErEW,GAAiCte,EAAAA,EAAAA,cAAagI,IACnD+V,EAAyB/V,EAAGlD,OAAOoD,QAAQ,GACzC,IAEGqW,GAAyBve,EAAAA,EAAAA,cAAagI,IAC3C6V,EAAiB7V,EAAGlD,OAAOkQ,MAAM,GAC/B,IAEGwJ,IAAwBxe,EAAAA,EAAAA,cAAagI,IAC1C8V,EAAgB9V,EAAGlD,OAAOkQ,MAAM,GAC9B,IAEGyJ,IAAgCze,EAAAA,EAAAA,cACrC,CAAC0e,EAAsBtV,KAGtB,GAFAiM,IAEIjQ,EACHA,EAAesZ,OACT,CACN,MAAOljB,EAAOxD,GAASoR,EAAO7O,QAC9BokB,EAAAA,EAAAA,IAAgCvhB,EAAWpF,EAAOwD,EAAOkjB,EAC1D,IAED,CAACthB,EAAUiY,EAASjQ,IAGfwZ,IAA6B5e,EAAAA,EAAAA,cAAY,KAC1Cmd,IACHA,IACA9H,IACD,GACE,CAAC8H,EAAgB9H,KAEbwJ,GAAaC,KAAyBve,EAAAA,EAAAA,UAASqY,EAAAA,GAA0B,CAC/EnY,oBAAoB,EACpBE,YAAa,2BAEbC,UAAWA,CAACR,EAAUgJ,IAAWqV,GAA8Bre,EAAUgJ,GACzE2V,UAAWH,KAGNI,IAA8Bhf,EAAAA,EAAAA,cACnC,eAACiZ,EAAgBhS,UAAAhO,OAAA,QAAAT,IAAAyO,UAAA,IAAAA,UAAA,GAAQ,MAAK,IAC7B6X,GACI,OAAHplB,QAAG,IAAHA,OAAG,EAAHA,EAAK8B,MACLxD,EACA8gB,EACAC,EACAC,EACAC,EACA,GACF,CAAI,OAAHvf,QAAG,IAAHA,OAAG,EAAHA,EAAK8B,MAAOwd,EAAuBhhB,EAAO8gB,EAAeC,EAAc+F,KAGnEG,IAA2Bjf,EAAAA,EAAAA,cAAY,KAC5Cie,GAA0B,GAC1Be,IAA4B,EAA5BA,EAAmC,GACjC,CAACA,KAEEE,IAAW3d,EAAAA,EAAAA,IAAWsd,IACtBM,GAAWhC,IAAkBiC,EAAAA,EAAAA,IAAqBP,IAIlDQ,GAA2Bha,GAAYC,EAAAA,GAE7C,OACCzD,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,EACCF,EAAAA,EAAAA,KAAC6d,GAAwB,CACxBtK,QAASoJ,EACTlI,YAAY,MACZnS,MACC0Z,EACG,sCACA,kLAEJtH,UACEoH,IACA9b,EAAAA,EAAAA,KAAC8d,EAAAA,IAAoB,CACpBnd,KAAM,GACN6B,MAAO,CAAEG,MAAOoZ,EAAWgC,WAAY,MAAOC,cAAe,YAI5D/I,EAAI/U,SAEP2b,GAA0B,0BAE5Bxb,EAAAA,EAAAA,MAACsT,EAAAA,GAAK,CACLC,OAAQA,EACRC,QAASA,EACTlT,KAAK,MACLsd,sBAAoB,EACpBC,YAAU,EACVC,oBAAkB,EAAAje,SAAA,EAElBF,EAAAA,EAAAA,KAAC8T,EAAAA,GAAY,KACbzT,EAAAA,EAAAA,MAAC0T,EAAAA,GAAY,CAAA7T,SAAA,EACZF,EAAAA,EAAAA,KAACgU,EAAAA,GAAW,CAAA9T,SAAC,+BACbF,EAAAA,EAAAA,KAACiU,EAAAA,GAAgB,KACjB5T,EAAAA,EAAAA,MAAC6T,EAAAA,GAAS,CAAAhU,SAAA,EACTG,EAAAA,EAAAA,MAAC+d,EAAAA,GAAW,CAACC,GAAG,gBAAene,SAAA,EAC9BF,EAAAA,EAAAA,KAACse,EAAAA,EAAS,CAAC7b,QAAQ,eAAekH,GAAG,QAAOzJ,SAAC,oBAG7CF,EAAAA,EAAAA,KAACkZ,EAAAA,GAAS,CACTtQ,SAAQ,mHAAqH1I,UAE7HF,EAAAA,EAAAA,KAACue,EAAAA,IAAwB,OAE1Bve,EAAAA,EAAAA,KAACwe,EAAAA,GAA0B,CAC1BC,SAAU,IACVjL,MAAO8D,EACPlP,SAAU2U,QAIZ1c,EAAAA,EAAAA,MAAC+d,EAAAA,GAAW,CAAC5c,GAAG,MAAM6c,GAAG,eAAcne,SAAA,EACtCG,EAAAA,EAAAA,MAACoY,EAAAA,EAAI,CAACiG,WAAW,SAAQxe,SAAA,EACxBF,EAAAA,EAAAA,KAACse,EAAAA,EAAS,CAAC7b,QAAQ,eAAekH,GAAG,QAAOzJ,SAAC,mBAG7CF,EAAAA,EAAAA,KAACkZ,EAAAA,GAAS,CACTtQ,SAAS,6GACT4S,SAAU,CAAEmD,aAAc,QAASze,UAEnCF,EAAAA,EAAAA,KAACue,EAAAA,IAAwB,OAE1Bve,EAAAA,EAAAA,KAAC4e,EAAAA,EAAM,KACP5e,EAAAA,EAAAA,KAAC6e,EAAAA,EAAc,CAAClc,MAAM,MAAMgH,GAAG,MAAM1I,EAAE,SAASU,EAAE,YAClD3B,EAAAA,EAAAA,KAACyJ,EAAAA,EAAI,CAACC,GAAG,OAAO+L,UAAU,SAASC,SAAS,SAAQxV,SAAC,0DAItDF,EAAAA,EAAAA,KAACwe,EAAAA,GAA0B,CAC1BC,SAAU,IACVK,YAAU,EACVtL,MAAO+D,EACPnP,SAAU4U,GACV+B,WAAYxH,QAIdlX,EAAAA,EAAAA,MAAC+d,EAAAA,GAAW,CAAC5c,GAAG,QAAQ6c,GAAG,uBAAsBne,SAAA,EAChDF,EAAAA,EAAAA,KAACkI,EAAAA,EAAQ,CACRyB,GAAG,QACHxB,UAAWqP,EACXpP,SAAU0U,EAA+B5c,SACzC,6BAGDF,EAAAA,EAAAA,KAACkZ,EAAAA,GAAS,CAACtQ,SAAS,yJAAwJ1I,UAC3KF,EAAAA,EAAAA,KAACue,EAAAA,IAAwB,aAK5Bve,EAAAA,EAAAA,KAACuU,EAAAA,GAAW,CAAArU,UACXG,EAAAA,EAAAA,MAACQ,EAAAA,GAAM,CAAAX,SAAA,EACNG,EAAAA,EAAAA,MAACC,EAAAA,GAAG,CAAAJ,SAAA,CACF8b,IACAhc,EAAAA,EAAAA,KAACwU,EAAAA,EAAM,CACNC,YAAY,MACZ9K,GAAI,EACJ4J,QAASmJ,GAA0B,GACnCsC,SAAUtB,GACVpb,MAAO4Z,EAAqBhc,SAC5B,YAIFF,EAAAA,EAAAA,KAACwU,EAAAA,EAAM,CACNyK,YAAY,SACZ7Z,UAAWsY,GACXsB,SAAUtB,KAAanG,EACvBjV,MAAQiV,EAAqD,GAAtC,oCACvB9C,YAAY,OACZ9K,GAAI,EACJ4J,QAASiK,KAA8Btd,SACvC,UAGDF,EAAAA,EAAAA,KAACwU,EAAAA,EAAM,CAACjB,QAASM,EAASmL,SAAUtB,GAASxd,SAAC,cAI9Cyd,KACA3d,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAAAJ,UACHF,EAAAA,EAAAA,KAACkf,EAAAA,GAAW,CACXC,QAAQ,8CACRjlB,OAAO,wBAQd8F,EAAAA,EAAAA,KAACof,EAAAA,GAAiB,CACjB9c,MAAM,yCACN6c,QAAQ,8RACRE,cAAc,WACdC,cAAc,SACd1L,OAAQ4I,EACR+C,SAAU7C,GAA0B,GACpC8C,SAAU/B,OAET,G,iHC/RE,MAAMzK,GAAqC5W,EAAAA,EAAAA,OAAMC,IACvD,MAAM,eAAE0W,EAAc,aAAExW,EAAY,mBAAEsW,GAAuBxW,EAEvDkZ,EAAiB1C,IAAuBE,EAAeyC,aAE7D,OACCxV,EAAAA,EAAAA,KAACgB,EAAAA,GAAS,CACTE,MAAM,uBACNC,gBACCnB,EAAAA,EAAAA,KAACyf,EAA0B,CAC1B5M,mBAAoBA,EACpBE,eAAgBA,EAChBxW,aAAcA,IAGhB+E,KAAMoe,EAAAA,EACNzE,UAAW1F,EAAiBsJ,EAAAA,OAAiB7nB,EAC7CkkB,eAAgB3F,EAAiB,CAAEtU,EAAG,EAAGU,EAAG,EAAGgB,MAAO,mBAAiB3L,EACvE6K,aAAc,CAAEZ,EAAG,CAAEa,KAAM,OAAQC,GAAI,QAAUC,KAAM,CAAEF,KAAM,OAAQC,GAAI,UAC/D,IAIF0d,GAAyCrjB,EAAAA,EAAAA,OAAMC,IAC3D,MAAM,eAAE0W,EAAc,aAAExW,EAAY,mBAAEsW,GAAuBxW,EAEvDsjB,GACJpjB,EAAaoS,aAAepS,EAAa+L,aAAeyK,EAAeuE,cAEnEsI,GACJrjB,EAAaoS,aAAepS,EAAa+L,aAAeyK,EAAehJ,SAEnEwL,EAAiB1C,IAAuBE,EAAeyC,aAE7D,OACCnV,EAAAA,EAAAA,MAACC,EAAAA,GAAG,CAAAJ,SAAA,EACHG,EAAAA,EAAAA,MAACC,EAAAA,GAAG,CAAC8I,GAAG,QAAOlJ,SAAA,CACbqV,IACAvV,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACmV,UAAU,SAASrM,GAAG,QAAOlJ,SAAC,6DAGlC,+BAC2B0f,EAAqB,MAAQ7M,EAAehJ,SAAW,GAAG,MAAI,IAC1F,IAAItQ,KAAKsZ,EAAe/I,SAASxK,qBAAsB,OAExDmgB,IACAtf,EAAAA,EAAAA,MAAAJ,EAAAA,SAAA,CAAAC,SAAA,EACCF,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACgU,WAAW,OAAMpU,SAAC,sBACvBF,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAAC8I,GAAG,QAAOlJ,SAAE6S,EAAeuE,mBAGjCqI,IAAqB3f,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAACgU,WAAW,OAAMpU,SAAC,qBAC7CF,EAAAA,EAAAA,KAACM,EAAAA,GAAG,CAAAJ,SAAE6S,EAAewE,iBAChB,G,iFC4JD,SAASzgB,EAAaC,EAAeP,GAC3C,YAAiCQ,IAA1BD,EAAME,kBAAsE,IAArCF,EAAME,gBAAgBC,IAAIV,EACzE,CAyDA,SAASW,EACRJ,EACAP,EACAC,EACAY,GAEA,IAAKP,EAAaC,EAAOP,KAnC1B,SAAuBO,EAAeP,GACrC,YAAqCQ,IAA9BD,EAAM8oB,0BAA8E7oB,IAAzCD,EAAM8oB,oBAAoB3oB,IAAIV,EACjF,CAiCqCe,CAAcR,EAAOP,GACxD,MAAO,GAER,IAAIgB,EAAOT,EAAM8oB,oBAAqB3oB,IAAIV,GAS1C,OARIa,GAAYG,EAAKC,OAAS,IAC7BD,EAAOA,EAAKE,OAAOL,IAGhBZ,GAAce,EAAKC,OAAS,IAC/BD,EAAOA,EAAKE,QAAQC,GAlCtB,SAA4BlB,EAAoByB,GAC/C,OACCC,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAIE,WAC/BD,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAI+R,cAC/B9R,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAIG,gBAC/BF,EAAAA,EAAAA,IAAe1B,EAAYyB,EAAII,gBAEjC,CA2B4BC,CAAmB9B,EAAYkB,MAGnDH,CACR,CAQA,SAASsoB,EAAoBnoB,EAAkBoD,GAE9C,GAAIpD,EAAEmb,YAAYrb,SAAWsD,EAAE+X,YAAYrb,OAC1C,OAAOsD,EAAE+X,YAAYrb,OAASE,EAAEmb,YAAYrb,OAE7C,MAAMsoB,EAAqBC,KAAKC,IAAIC,MACnC,KACAvoB,EAAEmb,YAAYvZ,KAAK6b,GAAMA,EAAEpL,QAAQkC,aAMpC,OAJ2B8T,KAAKC,IAAIC,MACnC,KACAnlB,EAAE+X,YAAYvZ,KAAK6b,GAAMA,EAAEpL,QAAQkC,aAER6T,CAC7B,CAoCA,MAAMvnB,GAAaC,EAAAA,EAAAA,kBAAiB,CACnCC,KApUM,WACN,MAAO,CACNzB,qBAAiBD,EACjB6oB,yBAAqB7oB,EACrBka,wBAAoBla,EACpBqf,2BAAuBrf,EACvBmpB,gBAAYnpB,EAEd,EA6TC6B,SAAU,CACTsd,6BAlSK,SACNpf,EACAgC,GASA,MAAM,MACLvC,EAAK,cACL4f,EAAa,mBACblF,EAAkB,sBAClBmF,EAAqB,oCACrBE,EAAmC,gCACnCD,GACGvd,EAGEG,EAAYnC,EAAME,gBACrB,IAAIkC,IAAqB,IAAIC,MAAMC,KAAKtC,EAAME,iBAAkB,CAACT,GAAO,KACxE,IAAI2C,IAAqB,CAAC,CAAC3C,GAAO,KAG/B2pB,EAA0B,CAC/B7J,gCAAiCA,IAAmC,EACpEC,oCAAqCA,IAAuC,GAEvE6J,EAAgBrpB,EAAMopB,WACzB,IAAIhnB,IAAyB,IAAIC,MAAMC,KAAKtC,EAAMopB,YAAa,CAAC3pB,EAAO2pB,KACvE,IAAIhnB,IAAyB,CAAC,CAAC3C,EAAO2pB,KAEnCE,EAAqBjK,EAAc7c,KAAK5B,IAAMkS,OArDhC3R,EAqD4CP,EApDzD,IACHO,EACH4a,YAAa5a,EAAI4a,YAAYvZ,KAAK+b,IAC1B,IAAKA,EAAKtL,QAAS,IAAIvQ,KAAK6b,EAAItL,aAExC+I,eAAgB7a,EAAI6a,gBAAkB,IAClC7a,EAAI6a,eACP/I,QAAS,IAAIvQ,KAAKvB,EAAI6a,eAAe/I,WARxC,IAAqB9R,CAqD8C,IAUlE,MAAO,CACNjB,gBAAiBiC,EACjB2mB,oBATkB9oB,EAAM8oB,oBACtB,IAAI1mB,IAA6B,IAC9BC,MAAMC,KAAKtC,EAAM8oB,qBACpB,CAACrpB,EAAO6pB,KAER,IAAIlnB,IAA6B,CAAC,CAAC3C,EAAO6pB,KAK5CnP,mBAAoBA,EACpBmF,sBAAuBA,QAAyBrf,EAChDmpB,WAAYC,EAEd,EAgPEjD,gCAxOK,SACNpmB,EACAgC,GAEA,MAAM,MAAEiB,EAAK,MAAExD,EAAK,eAAEuc,GAAmBha,EAEnCkB,EADc9C,EAAcJ,EAAOP,EAAO,QAAIQ,GACpBuC,KAAKrB,GACpCA,EAAI8B,QAAUA,EACX9B,EACA,IACGA,EACH6a,eAAgBA,EACb,CACAuE,cAAevE,EAAeuE,cAC9BC,aAAcxE,EAAewE,aAC7BxN,SAAUgJ,EAAehJ,SACzBC,QAAS,IAAIvQ,KAAKsZ,EAAe/I,SACjCwL,aAAczC,EAAeyC,cAE7B,QAIP,MAAO,IACHze,EACH8oB,oBAAqB,IAAI1mB,IAA6B,IAClDC,MAAMC,KAAKtC,EAAM8oB,qBACpB,CAACrpB,EAAOyD,KAGX,EA2MEqmB,8BAnMK,SACNvpB,EACAgC,GAEA,MAAM,MAAEiB,EAAK,MAAExD,GAAUuC,EAEnBkB,EADc9C,EAAcJ,EAAOP,EAAO,QAAIQ,GACpBU,QAAQQ,GAAQA,EAAI8B,QAAUA,IAE9D,MAAO,IACHjD,EACH8oB,oBAAqB,IAAI1mB,IAA6B,IAClDC,MAAMC,KAAKtC,EAAM8oB,qBACpB,CAACrpB,EAAOyD,KAGX,EAqLEsmB,qBA7KK,SAA8BxpB,EAAeP,GAAwB,IAADgqB,EAC1E,MAAML,EAA6B,QAAnBK,EAAGzpB,EAAMopB,kBAAU,IAAAK,OAAA,EAAhBA,EAAkBtpB,IAAIV,GACzC,IAAK2pB,EACJ,OAAOppB,EAGR,MAAM0pB,EAAiC,IACnCN,EACH5J,qCAAqC,EACrCD,iCAAiC,GAGlC,MAAO,IACHvf,EACHopB,WAAY,IAAIhnB,IAAyB,IACrCC,MAAMC,KAAKtC,EAAMopB,YACpB,CAAC3pB,EAAOiqB,KAGX,GA4JC7lB,UAAW,CACV9D,eACA+e,oBAzIK,SACN9e,EACAP,GAME,IAADkqB,EACD,IAAK3pB,EAAME,gBACV,MAAO,MAACD,OAAWA,OAAWA,OAAWA,GAE1C,MAAMmpB,EAA6B,QAAnBO,EAAG3pB,EAAMopB,kBAAU,IAAAO,OAAA,EAAhBA,EAAkBxpB,IAAIV,GACzC,MAAO,CACNO,EAAMma,mBACNna,EAAMsf,sBACI,OAAV8J,QAAU,IAAVA,OAAU,EAAVA,EAAY7J,gCACF,OAAV6J,QAAU,IAAVA,OAAU,EAAVA,EAAY5J,oCAEd,EAuHER,mBAxCK,SAA4Bhf,EAAegC,GACjD,MAAM,MAAEvC,EAAK,WAAEC,GAAesC,EAO9B,OANa5B,EACZJ,EACAP,EACAC,GACCkB,GAAMA,EAAEmb,YAAYrb,OAAS,GAA0B,OAArBE,EAAEob,iBAE1BjY,KAAKglB,EAClB,EAgCE7J,0BAzBK,SACNlf,EACAgC,GAEA,MAAM,MAAEvC,EAAK,WAAEC,GAAesC,EAE9B,OADa5B,EAAcJ,EAAOP,EAAOC,GAAakB,GAA2B,OAArBA,EAAEob,iBAClDjY,MAAK,CAACnD,EAAGoD,IAAMA,EAAEgY,eAAgB/I,QAAQkC,UAAYvU,EAAEob,eAAgB/I,QAAQkC,WAC5F,KAqBA7Q,EAAAA,EAAMC,eAAe9C,EAAW+C,YAAa,iBAEtC,MAAQC,eAAgBmlB,EAAsBjlB,eAAgBka,GAA0Bpd,C,2DC9WxF,SAAS2d,EACfva,EACApF,EACA4f,EACAlF,EACAmF,EACAC,EACAC,GAEA3a,EACC+kB,EAAAA,GAAqBxK,6BAA6B,CACjD3f,QACA4f,gBACAlF,qBACAmF,wBACAC,kCACAC,wCAGH,CASO,SAAS4G,EACfvhB,EACApF,EACAwD,EACA+Y,GAEAnX,EAAS+kB,EAAAA,GAAqBxD,gCAAgC,CAAEnjB,QAAOxD,QAAOuc,mBAC/E,C","sources":["ao/state/widgets/homegrownApps.ts","ao/store-methods/homegrownApps.ts","ao/components/Dashboard/widgets/homegrownApps/helperComponents/HomegrownAppRow.tsx","ao/components/Dashboard/widgets/homegrownApps/HomegrownAppsWidget.tsx","ao/state/widgets/inProgressApps.ts","ao/state/widgets/liveApps.ts","ao/components/Dashboard/widgets/inProgressApps/helperComponents/DownloadApprovedInfo.tsx","ao/components/Dashboard/widgets/inProgressApps/helperComponents/InProgressAppRow.tsx","ao/store-methods/inProgressApps.ts","ao/store-methods/liveApps.ts","ao/components/Dashboard/widgets/inProgressApps/InProgressAppsWidget.tsx","ao/components/Dashboard/widgets/liveApps/helperComponents/LiveAppRow.tsx","ao/components/Dashboard/widgets/liveApps/LiveAppsWidget.tsx","ao/components/Dashboard/widgets/nominatedApps/helperComponents/NominatedAppRow.tsx","ao/components/Dashboard/widgets/nominatedApps/helperComponents/NominatedAppsButtons.tsx","ao/components/Dashboard/widgets/nominatedApps/helperComponents/NominationInfo.tsx","ao/components/Dashboard/widgets/nominatedApps/NominatedAppsWidget.tsx","ao/components/Dashboard/data/data.ts","ao/components/Dashboard/widgetHelpers/WidgetActionButton.tsx","ao/components/Dashboard/widgetHelpers/WidgetAppBadge.tsx","ao/components/Dashboard/widgetHelpers/WidgetAppRow.tsx","ao/components/Dashboard/widgetHelpers/WidgetSpinner.tsx","ao/components/Dashboard/widgetHelpers/WidgetTable.tsx","ao/components/Dashboard/widgetHelpers/WidgetTag.tsx","ao/components/Dashboard/widgets/nominatedApps/helperComponents/MarkNotImplementingNowButton.tsx","ao/components/Dashboard/widgets/nominatedApps/helperComponents/NotImplementingNowInfo.tsx","ao/state/widgets/nominatedApps.ts","ao/store-methods/nominatedApps.ts"],"sourcesContent":["/**\r\n * @copyright Copyright 2021-2024 Epic Systems Corporation\r\n * @file state/store for homegrown apps widget\r\n * @module Epic.AppOrchard.State.InProgressApps\r\n */\r\n\r\nimport { buildSharedState } from \"@epic/react-redux-booster\";\r\nimport { ClientApplicationStatus } from \"ao/data\";\r\nimport store from \"ao/store\";\r\nimport { CustomerAppChangeRequestType, ICustomerAppLicense, IHomegrownApp } from \"ao/types\";\r\nimport { searchHasMatch } from \"ao/utils/helpers\";\r\n\r\n/// TYPES ///\r\n\r\nexport interface IState {\r\n\t// Map between the org ID and the in apps for a customer org\r\n\treadonly appsForOrg: Map<number, IHomegrownApp[]> | undefined;\r\n\t// Whether app data has been loaded for a customer org\r\n\treadonly hasLoadedForOrg: Map<number, boolean> | undefined;\r\n\treadonly orgCurrentEpicVersions: Map<number, number | null> | undefined;\r\n\treadonly isLocalJKUWarningEnabledForFeb24: boolean;\r\n}\r\n\r\n/**\r\n * Search params to identify the apps to select from the store\r\n */\r\ninterface IAppsSelectorParams {\r\n\torgId: number;\r\n\tsearchTerm: string;\r\n\tcurrentUserId: number;\r\n\tcreatedByCurrentUserOnly: boolean;\r\n\tchangeRequestsOnly: boolean;\r\n\tincludeAllRelatedOrgApps: boolean;\r\n}\r\n\r\n/**\r\n * Param set used to make sure we update all apps in the store after an update is made to the server\r\n * @param orgId org ID to use\r\n * @returns\r\n */\r\nfunction getEmptyFilterParamsForOrg(orgId: number) {\r\n\tconst emptyFilterParams: IAppsSelectorParams = {\r\n\t\torgId: orgId,\r\n\t\tsearchTerm: \"\",\r\n\t\tcurrentUserId: 0,\r\n\t\tcreatedByCurrentUserOnly: false,\r\n\t\tchangeRequestsOnly: false,\r\n\t\tincludeAllRelatedOrgApps: true,\r\n\t};\r\n\treturn emptyFilterParams;\r\n}\r\n\r\n/// INIT ///\r\n\r\n/**\r\n * Returns an empty initial state\r\n */\r\nexport function getInitialState(): IState {\r\n\treturn {\r\n\t\thasLoadedForOrg: undefined,\r\n\t\tappsForOrg: undefined,\r\n\t\torgCurrentEpicVersions: undefined,\r\n\t\tisLocalJKUWarningEnabledForFeb24: false,\r\n\t};\r\n}\r\n\r\n//#region REDUCERS\r\n\r\n/**\r\n * Make JS Date objects from string dates loaded from the server\r\n * @param app app to transform\r\n * @returns app with JS Date objects\r\n */\r\nfunction makeAppJSDates(app: IHomegrownApp): IHomegrownApp {\r\n\treturn {\r\n\t\t...app,\r\n\t\tcreatedOn: app.createdOn && new Date(app.createdOn),\r\n\t\tlicense: makeLicenseJSDates(app.license),\r\n\t};\r\n}\r\n\r\n/**\r\n * Make JS Date objects from string dates loaded from the server\r\n * @param app app to transform\r\n * @returns app with JS Date objects\r\n */\r\nfunction makeLicenseJSDates(lic: ICustomerAppLicense): ICustomerAppLicense {\r\n\treturn {\r\n\t\t...lic,\r\n\t\tnonProdLicensedOn: lic.nonProdLicensedOn && new Date(lic.nonProdLicensedOn),\r\n\t\tprodLicensedOn: lic.prodLicensedOn && new Date(lic.prodLicensedOn),\r\n\t\tchangeRequestedOn: lic.changeRequestedOn && new Date(lic.changeRequestedOn),\r\n\t};\r\n}\r\n\r\n/**\r\n * Update apps for a customer org and mark apps as loaded from server\r\n * @param state current state\r\n * @param params reducer params (org ID and apps to add)\r\n * @returns updated state\r\n */\r\nexport function updateAppsAfterLoad(\r\n\tstate: IState,\r\n\tparams: {\r\n\t\torgId: number;\r\n\t\tapps: IHomegrownApp[];\r\n\t\torgCurrentEpicVersion: number | null;\r\n\t\tisLocalJKUWarningEnabled: boolean;\r\n\t},\r\n): IState {\r\n\tconst { orgId, apps, orgCurrentEpicVersion, isLocalJKUWarningEnabled } = params;\r\n\r\n\t// update state to indicate we've loaded data for this org\r\n\tvar loadedMap = state.hasLoadedForOrg\r\n\t\t? new Map<number, boolean>([...Array.from(state.hasLoadedForOrg), [orgId, true]])\r\n\t\t: new Map<number, boolean>([[orgId, true]]);\r\n\r\n\tconst appsEntryForOrg = apps.map((a) => makeAppJSDates(a));\r\n\r\n\t// update data loaded for the org\r\n\tconst appsMap = state.appsForOrg\r\n\t\t? new Map<number, IHomegrownApp[]>([...Array.from(state.appsForOrg), [orgId, appsEntryForOrg]])\r\n\t\t: new Map<number, IHomegrownApp[]>([[orgId, appsEntryForOrg]]);\r\n\r\n\tconst versionsMap = state.orgCurrentEpicVersions\r\n\t\t? new Map<number, number | null>([\r\n\t\t\t\t...Array.from(state.orgCurrentEpicVersions),\r\n\t\t\t\t[orgId, orgCurrentEpicVersion],\r\n\t\t ])\r\n\t\t: new Map<number, number | null>([[orgId, orgCurrentEpicVersion]]);\r\n\r\n\treturn {\r\n\t\thasLoadedForOrg: loadedMap,\r\n\t\tappsForOrg: appsMap,\r\n\t\torgCurrentEpicVersions: versionsMap,\r\n\t\tisLocalJKUWarningEnabledForFeb24: isLocalJKUWarningEnabled,\r\n\t};\r\n}\r\n\r\nexport function markAsInternal(state: IState, params: { appId: number; orgId: number }): IState {\r\n\tconst { appId, orgId } = params;\r\n\tconst currentApps = getAppsOfType(state, getEmptyFilterParamsForOrg(orgId));\r\n\tconst updatedApps = currentApps.map((app) =>\r\n\t\tapp.appId !== appId\r\n\t\t\t? app\r\n\t\t\t: {\r\n\t\t\t\t\t...app,\r\n\t\t\t\t\tstatus: ClientApplicationStatus.Internal,\r\n\t\t\t },\r\n\t);\r\n\r\n\treturn {\r\n\t\thasLoadedForOrg: state.hasLoadedForOrg,\r\n\t\torgCurrentEpicVersions: state.orgCurrentEpicVersions,\r\n\t\tappsForOrg: new Map<number, IHomegrownApp[]>([\r\n\t\t\t...Array.from(state.appsForOrg!),\r\n\t\t\t[orgId, updatedApps],\r\n\t\t]),\r\n\t\tisLocalJKUWarningEnabledForFeb24: state.isLocalJKUWarningEnabledForFeb24,\r\n\t};\r\n}\r\n\r\n/**\r\n * Update (potentially deleting) change request after saving updates to server.\r\n * @param state current state\r\n * @param params reducer params to find org's app to update and how\r\n * @returns updated status\r\n */\r\nexport function updateChangeRequest(\r\n\tstate: IState,\r\n\tparams: {\r\n\t\tappId: number;\r\n\t\torgId: number;\r\n\t\tchangeType: CustomerAppChangeRequestType | null;\r\n\t\tcomment: string | null;\r\n\t},\r\n): IState {\r\n\tconst { appId, orgId, changeType, comment } = params;\r\n\tconst currentApps = getAppsOfType(state, getEmptyFilterParamsForOrg(orgId));\r\n\tconst isDelete = changeType === null;\r\n\tconst updatedApps = currentApps.map((app) =>\r\n\t\tapp.appId !== appId\r\n\t\t\t? app\r\n\t\t\t: {\r\n\t\t\t\t\t...app,\r\n\t\t\t\t\tlicense: {\r\n\t\t\t\t\t\t...app.license,\r\n\t\t\t\t\t\tchangeRequestType: changeType,\r\n\t\t\t\t\t\tchangeRequestComment: isDelete ? null : comment,\r\n\t\t\t\t\t\t// set these fields to current time/user so\r\n\t\t\t\t\t\t// we don't need to reload anything from the server after update\r\n\t\t\t\t\t\tchangeRequestedOn: isDelete ? null : new Date(),\r\n\t\t\t\t\t\tchangeRequestedByUserName: isDelete ? null : \"You\",\r\n\t\t\t\t\t},\r\n\t\t\t },\r\n\t);\r\n\r\n\treturn {\r\n\t\thasLoadedForOrg: state.hasLoadedForOrg,\r\n\t\torgCurrentEpicVersions: state.orgCurrentEpicVersions,\r\n\t\tappsForOrg: new Map<number, IHomegrownApp[]>([\r\n\t\t\t...Array.from(state.appsForOrg!),\r\n\t\t\t[orgId, updatedApps],\r\n\t\t]),\r\n\t\tisLocalJKUWarningEnabledForFeb24: state.isLocalJKUWarningEnabledForFeb24,\r\n\t};\r\n}\r\n\r\n//#endregion\r\n\r\n//#region SELECTORS\r\n\r\n/**\r\n * Check whether data has been loaded for a customer org\r\n * @param state current state\r\n * @param orgId: customer org id\r\n * @returns\r\n */\r\nexport function getHasLoaded(state: IState, orgId: number): boolean {\r\n\treturn state.hasLoadedForOrg !== undefined && state.hasLoadedForOrg.get(orgId) === true;\r\n}\r\n\r\nexport function getOrgCurrentEpicVersion(state: IState, orgId: number) {\r\n\tif (state.orgCurrentEpicVersions !== undefined) {\r\n\t\treturn state.orgCurrentEpicVersions.get(orgId);\r\n\t}\r\n}\r\n\r\nfunction hasDataForOrg(state: IState, orgId: number): boolean {\r\n\treturn state.appsForOrg !== undefined && state.appsForOrg.get(orgId) !== undefined;\r\n}\r\n\r\n/**\r\n * Helper to filter apps by search term\r\n * @param searchTerm search term to filter apps on\r\n * @param app app being considered for inclusion in results\r\n * @returns true if passes filter else false\r\n */\r\nfunction filterBySearchTerm(searchTerm: string, app: IHomegrownApp): boolean {\r\n\treturn (\r\n\t\tsearchHasMatch(searchTerm, app.appName) ||\r\n\t\tsearchHasMatch(searchTerm, app.prodClientId) ||\r\n\t\tsearchHasMatch(searchTerm, app.nonProdClientId)\r\n\t);\r\n}\r\n\r\n/**\r\n * Shared helper that filters to apps of a given type + search term filtering\r\n *\r\n * Checks if data has been loaded for the org too\r\n * @param state current state\r\n * @param orgId customer org ID\r\n * @param searchTerm search term to further filter matching apps\r\n * @param filterFn function to filter to type of app\r\n * @returns list of apps matching filters\r\n */\r\nfunction getAppsOfType(\r\n\tstate: IState,\r\n\tfilterParams: IAppsSelectorParams,\r\n\tfilterFn?: ((app: IHomegrownApp) => boolean) | undefined,\r\n): IHomegrownApp[] {\r\n\tconst {\r\n\t\torgId,\r\n\t\tsearchTerm,\r\n\t\tcurrentUserId,\r\n\t\tcreatedByCurrentUserOnly,\r\n\t\tchangeRequestsOnly,\r\n\t\tincludeAllRelatedOrgApps,\r\n\t} = filterParams;\r\n\tif (!getHasLoaded(state, orgId) || !hasDataForOrg(state, orgId)) {\r\n\t\treturn [];\r\n\t}\r\n\tlet apps = state.appsForOrg!.get(orgId)!;\r\n\r\n\tif (createdByCurrentUserOnly && apps.length > 0) {\r\n\t\tapps = apps.filter((a) => a.createdBy === currentUserId);\r\n\t}\r\n\r\n\tif (changeRequestsOnly && apps.length > 0) {\r\n\t\tapps = apps.filter((a) => a.license.changeRequestType !== null);\r\n\t}\r\n\r\n\tif (!includeAllRelatedOrgApps && apps.length > 0) {\r\n\t\tapps = apps.filter(\r\n\t\t\t(a) => !a.owningOrgName || a.license.isActivatedInNonProd || a.license.isActivatedInProd,\r\n\t\t);\r\n\t}\r\n\r\n\tif (filterFn && apps.length > 0) {\r\n\t\tapps = apps.filter(filterFn);\r\n\t}\r\n\r\n\tif (searchTerm && apps.length > 0) {\r\n\t\tapps = apps.filter((a) => filterBySearchTerm(searchTerm, a));\r\n\t}\r\n\r\n\treturn apps;\r\n}\r\n\r\n/**\r\n * Get all draft apps\r\n * @param state current state\r\n * @param params filter params\r\n */\r\nexport function getDraftApps(state: IState, filterParams: IAppsSelectorParams): IHomegrownApp[] {\r\n\tconst apps = getAppsOfType(\r\n\t\tstate,\r\n\t\tfilterParams,\r\n\t\t(a) => !a.license.isActivatedInNonProd && !a.license.isActivatedInProd,\r\n\t);\r\n\treturn apps.sort((a, b) => a.appName.localeCompare(b.appName));\r\n}\r\n\r\n/**\r\n * Get apps that have been activated for testing\r\n * @param state current state\r\n * @param params filter params\r\n */\r\nexport function getAppsActivatedForTesting(\r\n\tstate: IState,\r\n\tfilterParams: IAppsSelectorParams,\r\n): IHomegrownApp[] {\r\n\tconst apps = getAppsOfType(\r\n\t\tstate,\r\n\t\tfilterParams,\r\n\t\t(a) => a.license.isActivatedInNonProd === true && !a.license.isActivatedInProd,\r\n\t);\r\n\treturn apps.sort((a, b) => a.appName.localeCompare(b.appName));\r\n}\r\n\r\n/**\r\n * Get apps that have been activated for production\r\n * @param state current state\r\n * @param params filter params\r\n */\r\nexport function getAppsActivatedForProd(state: IState, filterParams: IAppsSelectorParams): IHomegrownApp[] {\r\n\tconst apps = getAppsOfType(state, filterParams, (a) => a.license.isActivatedInProd === true);\r\n\treturn apps.sort((a, b) => a.appName.localeCompare(b.appName));\r\n}\r\n\r\nexport function getIsLocalJKUWarningEnabledForFeb24(state: IState): boolean {\r\n\treturn state.isLocalJKUWarningEnabledForFeb24;\r\n}\r\n\r\n//#endregion\r\n\r\n/// BUILD IT ///\r\n\r\nconst builtState = buildSharedState({\r\n\tinit: getInitialState,\r\n\treducers: {\r\n\t\tupdateAppsAfterLoad,\r\n\t\tmarkAsInternal,\r\n\t\tupdateChangeRequest,\r\n\t},\r\n\tselectors: {\r\n\t\tgetHasLoaded,\r\n\t\tgetDraftApps,\r\n\t\tgetAppsActivatedForTesting,\r\n\t\tgetAppsActivatedForProd,\r\n\t\tgetOrgCurrentEpicVersion,\r\n\t\tgetIsLocalJKUWarningEnabledForFeb24,\r\n\t},\r\n});\r\n\r\nstore.addSharedState(builtState.sharedState, \"homegrownApps\");\r\n\r\nexport const { actionCreators: homegrownAppsActions, useSharedState: useHomegrownAppsState } = builtState;\r\n","/**\r\n * @copyright Copyright 2021-2024 Epic Systems Corporation\r\n * @file homegrown apps store updater methods\r\n * @module Epic.AppOrchard.StoreMethods.HomegrownApps\r\n */\r\n\r\nimport { IDispatch } from \"@epic/react-redux-booster\";\r\nimport { homegrownAppsActions } from \"ao/state/widgets/homegrownApps\";\r\nimport { CustomerAppChangeRequestType, IHomegrownApp } from \"ao/types\";\r\n\r\n/**\r\n * Update store with apps after loading from server\r\n * @param dispatch for useDispatch\r\n * @param orgId customer org id\r\n * @param apps apps for customer org\r\n * @param orgCurrentEpicVersion current Epic version for the org\r\n */\r\nexport function updateAppsAfterLoad(\r\n\tdispatch: IDispatch,\r\n\torgId: number,\r\n\tapps: IHomegrownApp[],\r\n\torgCurrentEpicVersion: number | null,\r\n\tisLocalJKUWarningEnabled: boolean,\r\n) {\r\n\tdispatch(\r\n\t\thomegrownAppsActions.updateAppsAfterLoad({\r\n\t\t\torgId,\r\n\t\t\tapps,\r\n\t\t\torgCurrentEpicVersion,\r\n\t\t\tisLocalJKUWarningEnabled,\r\n\t\t}),\r\n\t);\r\n}\r\n\r\n/**\r\n * Mark app as internal\r\n * @param dispatch for useDispatch\r\n * @param orgId customer org id\r\n * @param appId customer app ID\r\n */\r\nexport function markAsInternal(dispatch: IDispatch, appId: number, orgId: number) {\r\n\tdispatch(homegrownAppsActions.markAsInternal({ appId, orgId }));\r\n}\r\n\r\n/**\r\n * Update (potentially deleting) change request after saving updates to server\r\n * @param dispatch for useDispatch\r\n * @param orgId customer org id\r\n * @param appId customer app ID\r\n */\r\nexport function updateChangeRequest(\r\n\tdispatch: IDispatch,\r\n\tappId: number,\r\n\torgId: number,\r\n\tchangeType: CustomerAppChangeRequestType | null,\r\n\tcomment: string | null,\r\n) {\r\n\tdispatch(homegrownAppsActions.updateChangeRequest({ appId, orgId, changeType, comment }));\r\n}\r\n","/**\r\n * @copyright Copyright 2021-2025 Epic Systems Corporation\r\n * @file One row representing one app in the Homegrown Apps widget\r\n * @module Epic.AppOrchard.Dashboard.HomegrownAppRow\r\n */\r\n\r\nimport { CalendarIcon } from \"@chakra-ui/icons\";\r\nimport { Box, ListItem, UnorderedList, VStack } from \"@chakra-ui/react\";\r\nimport { useAsync } from \"@epic/react-async-hook\";\r\nimport { IDispatch } from \"@epic/react-redux-booster\";\r\nimport {\r\n\tAOLink,\r\n\tAppCredentialsLink,\r\n\tAppStatusTag,\r\n\tMarkInternalButton,\r\n\tNewVersionLink,\r\n\tRequestCustomerAppChangeButton,\r\n\tUpdateCustomerAppLicenseButton,\r\n} from \"ao/components/Core\";\r\nimport { getAttestation, updateCustomerAppLicenseState } from \"ao/components/Dashboard/data\";\r\nimport { WidgetActionButton, WidgetAppRow, WidgetTag } from \"ao/components/Dashboard/widgetHelpers\";\r\nimport { ClientApplicationStatus, EnvironmentType, IAttestationModel } from \"ao/data\";\r\nimport { useSiteInfoState } from \"ao/state/siteInfo\";\r\nimport { markAsInternal, updateAppsAfterLoad, updateChangeRequest } from \"ao/store-methods/homegrownApps\";\r\nimport { CustomerAppChangeRequestType, CustomerAppLicense, IHomegrownApp, IUserSecurity } from \"ao/types\";\r\nimport { IHomegrownAppsForOrgResponseModel } from \"ao/types/dashboard\";\r\nimport { isNullOrEmpty } from \"ao/utils/helpers\";\r\nimport { isInFlight } from \"ao/utils/useAsyncHelpers\";\r\nimport { FC, memo, useCallback, useMemo, useState } from \"react\";\r\nimport { BiMessageRoundedDetail } from \"react-icons/bi\";\r\nimport { GiNewShoot } from \"react-icons/gi\";\r\nimport { ImStatsBars } from \"react-icons/im\";\r\nimport { IoSpeedometerOutline } from \"react-icons/io5\";\r\n\r\nfunction formattedChangeRequest(changeType: CustomerAppChangeRequestType) {\r\n\tswitch (changeType) {\r\n\t\tcase CustomerAppChangeRequestType.NonProdActivation:\r\n\t\t\treturn \"be activated for non-production\";\r\n\t\tcase CustomerAppChangeRequestType.ProdActivation:\r\n\t\t\treturn \"be activated for production\";\r\n\t\tcase CustomerAppChangeRequestType.NonProdCredentialUpdate:\r\n\t\t\treturn \"have its credentials updated for non-production\";\r\n\t\tcase CustomerAppChangeRequestType.ProdCredentialUpdate:\r\n\t\t\treturn \"have its credentials updated for production\";\r\n\t\tdefault:\r\n\t\t\treturn \"\";\r\n\t}\r\n}\r\n\r\ninterface IProps {\r\n\tapp: IHomegrownApp;\r\n\tuserSecurity: IUserSecurity;\r\n\tbaseUrl: string;\r\n\torgId: number;\r\n\torgCurrentEpicVersion: number;\r\n\tisLocalJKUWarningEnabled: boolean;\r\n\tdispatch: IDispatch;\r\n}\r\n\r\n/** One row representing one app in the Homegrown apps widget */\r\nexport const HomegrownAppRow: FC<IProps> = memo((props: IProps) => {\r\n\tconst {\r\n\t\tapp,\r\n\t\tuserSecurity,\r\n\t\tbaseUrl,\r\n\t\torgId,\r\n\t\tdispatch,\r\n\t\torgCurrentEpicVersion,\r\n\t\tisLocalJKUWarningEnabled,\r\n\t} = props;\r\n\r\n\t//#region state/handlers\r\n\tconst isRelatedOrgApp = !!app.owningOrgName;\r\n\tconst appBaseUrl = userSecurity.isEpicCustomer\r\n\t\t? `${baseUrl}Developer/Edit?AppId=`\r\n\t\t: userSecurity.isEpicAdministrator || userSecurity.isSuperAdministrator\r\n\t\t? `${baseUrl}Developer/Review?AppId=`\r\n\t\t: \"\"; // no app page for non admin Epic staff yet\r\n\r\n\tconst hasAppUrl = appBaseUrl.length > 0;\r\n\tconst statsUrl = `${baseUrl}Stats?OrgId=${orgId}&ClientId=${app.prodClientId}`;\r\n\tconst metricsUrl = `${baseUrl}ApiMetrics?OrgId=${orgId}&ClientId=${app.prodClientId}`;\r\n\tconst isNewestAppVersion = app.appId === app.newestAppVersion;\r\n\tconst isLockedDown =\r\n\t\tapp.status === ClientApplicationStatus.Internal || app.status === ClientApplicationStatus.Active;\r\n\tconst [attestation, setAttestation] = useState<IAttestationModel | null>(null);\r\n\tconst { siteInfo } = useSiteInfoState((selectors) => selectors.getState(), []);\r\n\r\n\tconst licenseModel = useMemo(() => new CustomerAppLicense(app.license), [app.license]);\r\n\tconst hasCreds = useMemo(\r\n\t\t() =>\r\n\t\t\tlicenseModel.HasSavedCredsAnyEnv(\r\n\t\t\t\t!isNullOrEmpty(app.nonProdJsonWebKeySetUrl),\r\n\t\t\t\t!isNullOrEmpty(app.prodJsonWebKeySetUrl),\r\n\t\t\t),\r\n\t\t[app.nonProdJsonWebKeySetUrl, app.prodJsonWebKeySetUrl, licenseModel],\r\n\t);\r\n\tconst hasBottomContent =\r\n\t\t!isNewestAppVersion || hasCreds || app.hasApiStatsForOrg || app.hasApiMetricsForOrg;\r\n\r\n\tconst handleMarkInternal = useCallback(() => markAsInternal(dispatch, app.appId, orgId), [\r\n\t\tapp.appId,\r\n\t\tdispatch,\r\n\t\torgId,\r\n\t]);\r\n\r\n\t/** save change request updates to the store */\r\n\tconst handleUpdateChangeRequest = useCallback(\r\n\t\t(\r\n\t\t\tappId: number,\r\n\t\t\torgId: number,\r\n\t\t\tchangeType: CustomerAppChangeRequestType | null,\r\n\t\t\tchangeComment: string | null,\r\n\t\t) => updateChangeRequest(dispatch, appId, orgId, changeType, changeComment),\r\n\t\t[dispatch],\r\n\t);\r\n\r\n\tconst handleUpdateLicense = useCallback(\r\n\t\t(response: IHomegrownAppsForOrgResponseModel) =>\r\n\t\t\tupdateAppsAfterLoad(\r\n\t\t\t\tdispatch,\r\n\t\t\t\torgId,\r\n\t\t\t\tresponse.homegrownApps,\r\n\t\t\t\tresponse.orgCurrentEpicVersion,\r\n\t\t\t\tresponse.isLocalJKUWarningEnabledForFeb24,\r\n\t\t\t),\r\n\t\t[dispatch, orgId],\r\n\t);\r\n\r\n\tconst [attestationLoadingState] = useAsync(getAttestation, {\r\n\t\texecuteImmediately: siteInfo.isCustomerAppAttestationEnabled,\r\n\t\tdisplayName: \"loadAssociations\",\r\n\t\tonSuccess: (response) => {\r\n\t\t\tsetAttestation(response.attestation);\r\n\t\t},\r\n\t\tinitialArguments: [app.appId],\r\n\t});\r\n\r\n\tconst creationInfo =\r\n\t\t(app.createdByUserName ? `Created by ${app.createdByUserName} on ` : \"Created on \") +\r\n\t\t`${app.createdOn.toLocaleDateString()}.`;\r\n\r\n\t// activations that happened before the dedicated customer license table was created\r\n\t// wouldn't have activatedOn or activatedBy populated, but all activations since will have both fields populated\r\n\r\n\tconst nonProdActivationInfo =\r\n\t\t\"Activated for non-production\" +\r\n\t\t(!isNullOrEmpty(app.license.nonProdLicensedByUserName)\r\n\t\t\t? ` by ${\r\n\t\t\t\t\tapp.license.nonProdLicensedByUserName\r\n\t\t\t } on ${app.license.nonProdLicensedOn!.toLocaleDateString()}.`\r\n\t\t\t: \".\");\r\n\r\n\tconst prodActivationInfo =\r\n\t\t\"Activated for production\" +\r\n\t\t(!isNullOrEmpty(app.license.prodLicensedByUserName)\r\n\t\t\t? ` by ${\r\n\t\t\t\t\tapp.license.prodLicensedByUserName\r\n\t\t\t } on ${app.license.prodLicensedOn!.toLocaleDateString()}.`\r\n\t\t\t: \".\");\r\n\r\n\tconst appIsNotActivated = !app.license.isActivatedInNonProd && !app.license.isActivatedInProd;\r\n\r\n\tconst isAttestationLoading = isInFlight(attestationLoadingState);\r\n\r\n\t//#endregion\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t<WidgetAppRow\r\n\t\t\t\tappId={app.appId}\r\n\t\t\t\tappName={app.appName}\r\n\t\t\t\tsubtitle={isRelatedOrgApp && <Box>Created by {app.owningOrgName}</Box>}\r\n\t\t\t\tlinkUrl={hasAppUrl ? appBaseUrl + app.appId : undefined}\r\n\t\t\t\tlinkTitle={hasAppUrl ? \"Go to this app's page\" : undefined}\r\n\t\t\t\tbelowLogoContent={<AppStatusTag status={app.status} size=\"sm\"></AppStatusTag>}\r\n\t\t\t\tadditionalAppInfo={\r\n\t\t\t\t\t<VStack spacing=\"0.3em\" width=\"max-content\">\r\n\t\t\t\t\t\t<WidgetTag\r\n\t\t\t\t\t\t\tw=\"100%\"\r\n\t\t\t\t\t\t\tlabel={\"Events\"}\r\n\t\t\t\t\t\t\ttooltipContent={\r\n\t\t\t\t\t\t\t\tappIsNotActivated ? (\r\n\t\t\t\t\t\t\t\t\tcreationInfo\r\n\t\t\t\t\t\t\t\t) : (\r\n\t\t\t\t\t\t\t\t\t<UnorderedList>\r\n\t\t\t\t\t\t\t\t\t\t<ListItem>{creationInfo}</ListItem>\r\n\t\t\t\t\t\t\t\t\t\t{app.license.isActivatedInNonProd && (\r\n\t\t\t\t\t\t\t\t\t\t\t<ListItem>{nonProdActivationInfo}</ListItem>\r\n\t\t\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t\t\t\t{app.license.isActivatedInProd && (\r\n\t\t\t\t\t\t\t\t\t\t\t<ListItem>{prodActivationInfo}</ListItem>\r\n\t\t\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t\t\t</UnorderedList>\r\n\t\t\t\t\t\t\t\t)\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\ticon={CalendarIcon}\r\n\t\t\t\t\t\t></WidgetTag>\r\n\r\n\t\t\t\t\t\t{app.license.changeRequestType !== null && (\r\n\t\t\t\t\t\t\t<WidgetTag\r\n\t\t\t\t\t\t\t\tw=\"100%\"\r\n\t\t\t\t\t\t\t\tlabel=\"Changes Requested\"\r\n\t\t\t\t\t\t\t\ttooltipContent={\r\n\t\t\t\t\t\t\t\t\t<Box>\r\n\t\t\t\t\t\t\t\t\t\t{app.license.changeRequestedByUserName} requested that this app{\" \"}\r\n\t\t\t\t\t\t\t\t\t\t{formattedChangeRequest(app.license.changeRequestType)} on{\" \"}\r\n\t\t\t\t\t\t\t\t\t\t{app.license.changeRequestedOn?.toLocaleDateString()}.\r\n\t\t\t\t\t\t\t\t\t\t{app.license.changeRequestComment &&\r\n\t\t\t\t\t\t\t\t\t\t\tapp.license.changeRequestComment.length > 0 && (\r\n\t\t\t\t\t\t\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Box mt=\"0.5em\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tHere is the comment left by the requestor:{\" \"}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Box>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Box mt=\"0.5em\">{app.license.changeRequestComment}</Box>\r\n\t\t\t\t\t\t\t\t\t\t\t\t</>\r\n\t\t\t\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t\t\t</Box>\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\ticon={BiMessageRoundedDetail}\r\n\t\t\t\t\t\t\t\ticonProps={{ h: \"16px\", w: \"16px\", marginInlineEnd: \"0.25rem\" }}\r\n\t\t\t\t\t\t\t\ttooltipProps={{\r\n\t\t\t\t\t\t\t\t\tw: { base: \"65vw\", lg: \"15vw\" },\r\n\t\t\t\t\t\t\t\t\tmaxW: { base: \"65vw\", lg: \"15vw\" },\r\n\t\t\t\t\t\t\t\t}}\r\n\t\t\t\t\t\t\t></WidgetTag>\r\n\t\t\t\t\t\t)}\r\n\t\t\t\t\t</VStack>\r\n\t\t\t\t}\r\n\t\t\t\tbottomContent={\r\n\t\t\t\t\thasBottomContent && (\r\n\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t{!isNewestAppVersion &&\r\n\t\t\t\t\t\t\t\t(hasAppUrl ? (\r\n\t\t\t\t\t\t\t\t\t<NewVersionLink\r\n\t\t\t\t\t\t\t\t\t\tnewVersionUrl={appBaseUrl + app.newestAppVersion}\r\n\t\t\t\t\t\t\t\t\t\tappId={app.appId}\r\n\t\t\t\t\t\t\t\t\t\tnewestAppId={app.newestAppVersion!}\r\n\t\t\t\t\t\t\t\t\t\tisOwnApp\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t) : (\r\n\t\t\t\t\t\t\t\t\t<Box title=\"A newer version of this app exists\">\r\n\t\t\t\t\t\t\t\t\t\t<GiNewShoot\r\n\t\t\t\t\t\t\t\t\t\t\tstyle={{ display: \"inline-block\", marginRight: \"4px\" }}\r\n\t\t\t\t\t\t\t\t\t\t\tcolor=\"green\"\r\n\t\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t\tNewer App Version\r\n\t\t\t\t\t\t\t\t\t</Box>\r\n\t\t\t\t\t\t\t\t))}\r\n\t\t\t\t\t\t\t{hasCreds && (\r\n\t\t\t\t\t\t\t\t<AppCredentialsLink\r\n\t\t\t\t\t\t\t\t\tepicVersion={orgCurrentEpicVersion}\r\n\t\t\t\t\t\t\t\t\tisOwnApp={true}\r\n\t\t\t\t\t\t\t\t\tnonProdJsonWebKeySetUrl={app.nonProdJsonWebKeySetUrl}\r\n\t\t\t\t\t\t\t\t\tprodJsonWebKeySetUrl={app.prodJsonWebKeySetUrl}\r\n\t\t\t\t\t\t\t\t\ttestJwtSigningPublicKeyThumbprint={\r\n\t\t\t\t\t\t\t\t\t\tlicenseModel.testJwtSigningPublicKeyThumbprint\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tprodJwtSigningPublicKeyThumbprint={\r\n\t\t\t\t\t\t\t\t\t\tlicenseModel.prodJwtSigningPublicKeyThumbprint\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\ttestClientSecretHash={licenseModel.testClientSecretHash}\r\n\t\t\t\t\t\t\t\t\tprodClientSecretHash={licenseModel.prodClientSecretHash}\r\n\t\t\t\t\t\t\t\t\ttestPublicKeyBlobIsCSP={licenseModel.testPublicKeyBlobIsCSP}\r\n\t\t\t\t\t\t\t\t\tprodPublicKeyBlobIsCSP={licenseModel.prodPublicKeyBlobIsCSP}\r\n\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t{app.hasApiStatsForOrg && (\r\n\t\t\t\t\t\t\t\t<AOLink\r\n\t\t\t\t\t\t\t\t\turl={statsUrl}\r\n\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\r\n\t\t\t\t\t\t\t\t\ttitle=\"View stats for API calls this app has made\"\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t<ImStatsBars\r\n\t\t\t\t\t\t\t\t\t\tcolor=\"darkgoldenrod\"\r\n\t\t\t\t\t\t\t\t\t\tstyle={{ display: \"inline\", marginRight: \"4px\" }}\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\tAPI Stats\r\n\t\t\t\t\t\t\t\t</AOLink>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t{app.hasApiMetricsForOrg && (\r\n\t\t\t\t\t\t\t\t<AOLink\r\n\t\t\t\t\t\t\t\t\turl={metricsUrl}\r\n\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\r\n\t\t\t\t\t\t\t\t\ttitle=\"View performance metrics for API calls this app has made\"\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t<IoSpeedometerOutline\r\n\t\t\t\t\t\t\t\t\t\tcolor=\"darkgreen\"\r\n\t\t\t\t\t\t\t\t\t\tstyle={{ display: \"inline\", marginRight: \"4px\" }}\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\tAPI Performance\r\n\t\t\t\t\t\t\t\t</AOLink>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t</>\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t\tactions={\r\n\t\t\t\t\tuserSecurity.isEpicCustomer && (\r\n\t\t\t\t\t\t<VStack w=\"100%\" spacing=\"0.25em\">\r\n\t\t\t\t\t\t\t{!isLockedDown && !isRelatedOrgApp && (\r\n\t\t\t\t\t\t\t\t<MarkInternalButton\r\n\t\t\t\t\t\t\t\t\tattestation={attestation}\r\n\t\t\t\t\t\t\t\t\tisAttestationLoading={isAttestationLoading}\r\n\t\t\t\t\t\t\t\t\tappStatus={app.status}\r\n\t\t\t\t\t\t\t\t\tsuccessHandler={handleMarkInternal}\r\n\t\t\t\t\t\t\t\t\tappId={app.appId}\r\n\t\t\t\t\t\t\t\t\tbuttonAs={WidgetActionButton}\r\n\t\t\t\t\t\t\t\t\thasApiContextWarning={app.hasOutOfContextAPIs}\r\n\t\t\t\t\t\t\t\t\thasApiContextWarningOverride={app.hasApiContextValidationOverride}\r\n\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t{userSecurity.canActivateClients && (\r\n\t\t\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t\t\t<UpdateCustomerAppLicenseButton\r\n\t\t\t\t\t\t\t\t\t\tlicense={licenseModel}\r\n\t\t\t\t\t\t\t\t\t\tappStatus={app.status}\r\n\t\t\t\t\t\t\t\t\t\tepicVersion={orgCurrentEpicVersion}\r\n\t\t\t\t\t\t\t\t\t\tappUsesOAuth2={app.useOAuth2}\r\n\t\t\t\t\t\t\t\t\t\tappConsumerType={app.consumerType}\r\n\t\t\t\t\t\t\t\t\t\tappIsConfidentialClient={app.isConfidentialClient}\r\n\t\t\t\t\t\t\t\t\t\tenvType={EnvironmentType.NonProd}\r\n\t\t\t\t\t\t\t\t\t\tupdateLicenseApi={updateCustomerAppLicenseState}\r\n\t\t\t\t\t\t\t\t\t\tsuccessHandler={handleUpdateLicense}\r\n\t\t\t\t\t\t\t\t\t\tbuttonAs={WidgetActionButton}\r\n\t\t\t\t\t\t\t\t\t\tappJsonWebKeySetUrl={app.nonProdJsonWebKeySetUrl}\r\n\t\t\t\t\t\t\t\t\t\thasApiContextWarning={app.hasOutOfContextAPIs}\r\n\t\t\t\t\t\t\t\t\t\thasApiContextWarningOverride={app.hasApiContextValidationOverride}\r\n\t\t\t\t\t\t\t\t\t\tpublicKeysAllowed={app.publicKeysAllowed}\r\n\t\t\t\t\t\t\t\t\t\tgetsAppLicensesFromOrganization_Name={\r\n\t\t\t\t\t\t\t\t\t\t\tapp.getsAppLicensesFromOrganization_Name\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\tattestation={attestation}\r\n\t\t\t\t\t\t\t\t\t\tisLocalJKUWarningEnabledForFeb24={isLocalJKUWarningEnabled}\r\n\t\t\t\t\t\t\t\t\t\tisRelatedOrgApp={isRelatedOrgApp}\r\n\t\t\t\t\t\t\t\t\t\towningOrgName={app.owningOrgName}\r\n\t\t\t\t\t\t\t\t\t\tskipAttestation={false}\r\n\t\t\t\t\t\t\t\t\t\tisLoading={isAttestationLoading}\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t{/* Require internal/locked down status + non PRD activation ideally for PRD actions,\r\n\t\t\t\t\t\t\t\t\t\tbut if this app was already activated in PRD (e.g. from Edit Apps) allow updating PRD license */}\r\n\t\t\t\t\t\t\t\t\t{((isLockedDown && app.license.isActivatedInNonProd) ||\r\n\t\t\t\t\t\t\t\t\t\tapp.license.isActivatedInProd) && (\r\n\t\t\t\t\t\t\t\t\t\t<UpdateCustomerAppLicenseButton\r\n\t\t\t\t\t\t\t\t\t\t\tlicense={licenseModel}\r\n\t\t\t\t\t\t\t\t\t\t\tappStatus={app.status}\r\n\t\t\t\t\t\t\t\t\t\t\tepicVersion={orgCurrentEpicVersion}\r\n\t\t\t\t\t\t\t\t\t\t\tappUsesOAuth2={app.useOAuth2}\r\n\t\t\t\t\t\t\t\t\t\t\tappConsumerType={app.consumerType}\r\n\t\t\t\t\t\t\t\t\t\t\tappIsConfidentialClient={app.isConfidentialClient}\r\n\t\t\t\t\t\t\t\t\t\t\tenvType={EnvironmentType.Prod}\r\n\t\t\t\t\t\t\t\t\t\t\tupdateLicenseApi={updateCustomerAppLicenseState}\r\n\t\t\t\t\t\t\t\t\t\t\tsuccessHandler={handleUpdateLicense}\r\n\t\t\t\t\t\t\t\t\t\t\tbuttonAs={WidgetActionButton}\r\n\t\t\t\t\t\t\t\t\t\t\tappJsonWebKeySetUrl={app.prodJsonWebKeySetUrl}\r\n\t\t\t\t\t\t\t\t\t\t\thasApiContextWarning={app.hasOutOfContextAPIs}\r\n\t\t\t\t\t\t\t\t\t\t\thasApiContextWarningOverride={app.hasApiContextValidationOverride}\r\n\t\t\t\t\t\t\t\t\t\t\tpublicKeysAllowed={app.publicKeysAllowed}\r\n\t\t\t\t\t\t\t\t\t\t\tgetsAppLicensesFromOrganization_Name={\r\n\t\t\t\t\t\t\t\t\t\t\t\tapp.getsAppLicensesFromOrganization_Name\r\n\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\tattestation={attestation}\r\n\t\t\t\t\t\t\t\t\t\t\tisLocalJKUWarningEnabledForFeb24={isLocalJKUWarningEnabled}\r\n\t\t\t\t\t\t\t\t\t\t\tisRelatedOrgApp={isRelatedOrgApp}\r\n\t\t\t\t\t\t\t\t\t\t\towningOrgName={app.owningOrgName}\r\n\t\t\t\t\t\t\t\t\t\t\tskipAttestation={false}\r\n\t\t\t\t\t\t\t\t\t\t\tisLoading={isAttestationLoading}\r\n\t\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t\t</>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t{!app.getsAppLicensesFromOrganization_Name && (\r\n\t\t\t\t\t\t\t\t<RequestCustomerAppChangeButton\r\n\t\t\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\t\t\tlicense={app.license}\r\n\t\t\t\t\t\t\t\t\tsuccessHandler={handleUpdateChangeRequest}\r\n\t\t\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t\t\t\tbuttonAs={WidgetActionButton}\r\n\t\t\t\t\t\t\t\t></RequestCustomerAppChangeButton>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t</VStack>\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t></WidgetAppRow>\r\n\t\t</>\r\n\t);\r\n});\r\n","/* eslint-disable @typescript-eslint/no-unused-vars */\r\n/**\r\n * @copyright Copyright 2021-2024 Epic Systems Corporation\r\n * @file Homegrown (customer) apps dashboard widget\r\n * @module Epic.AppOrchard.Dashboard.Widgets.HomegrownAppsWidget\r\n */\r\n\r\nimport { Checkbox } from \"@chakra-ui/checkbox\";\r\nimport { Box } from \"@chakra-ui/layout\";\r\nimport { Text } from \"@chakra-ui/react\";\r\nimport { ISuccessHandler, useAsync } from \"@epic/react-async-hook\";\r\nimport { useDispatch } from \"@epic/react-redux-booster\";\r\nimport { config } from \"ao/appConfig\";\r\nimport { AsyncPlaceholder, ITab, SearchInput, TabbedSection } from \"ao/components/Core\";\r\nimport { getHomegrownApps } from \"ao/components/Dashboard/data\";\r\nimport { useHomegrownAppsState } from \"ao/state/widgets/homegrownApps\";\r\nimport { updateAppsAfterLoad } from \"ao/store-methods/homegrownApps\";\r\nimport { IWidget, IWidgetProps } from \"ao/types/dashboard\";\r\nimport { getBaseUrl } from \"ao/utils/helpers\";\r\nimport React, { ChangeEvent, useCallback, useEffect, useMemo, useState } from \"react\";\r\nimport { WidgetSpinner, WidgetTable } from \"../../widgetHelpers\";\r\nimport { HomegrownAppRow } from \"./helperComponents/HomegrownAppRow\";\r\n\r\nfunction getNumFiltersApplied(...args: boolean[]): number {\r\n\treturn args.filter((a) => a === true).length;\r\n}\r\n\r\n/** Homegrown (customer) apps dashboard widget */\r\nexport const HomegrownAppsWidget: IWidget = (props: IWidgetProps) => {\r\n\tconst {\r\n\t\tisExpanded,\r\n\t\torgId,\r\n\t\tuserSecurity,\r\n\t\tonFiltersUpdate,\r\n\t\tonNumFiltersAppliedUpdate,\r\n\t\tnumFiltersApplied,\r\n\t} = props;\r\n\r\n\t//#region state/handlers\r\n\tconst [searchTerm, setSearchTerm] = useState<string>(\"\");\r\n\tconst handleChangeSearchTerm = useCallback((newSearchTerm: string) => setSearchTerm(newSearchTerm), []);\r\n\tconst [createdByCurrentUserOnly, setCreatedByCurrentUserOnly] = useState<boolean>(false);\r\n\tconst [changeRequestsOnly, setChangeRequestsOnly] = useState<boolean>(false);\r\n\tconst [includeAllRelatedOrgApps, setIncludeAllRelatedOrgApps] = useState<boolean>(false);\r\n\r\n\tconst handleCreatedByCurrentUserChecked = useCallback(\r\n\t\t(ev: ChangeEvent<HTMLInputElement>) => {\r\n\t\t\tconst createdByCurrentUserChecked = ev.target.checked;\r\n\t\t\tonNumFiltersAppliedUpdate &&\r\n\t\t\t\tonNumFiltersAppliedUpdate(\r\n\t\t\t\t\tgetNumFiltersApplied(\r\n\t\t\t\t\t\tcreatedByCurrentUserChecked,\r\n\t\t\t\t\t\tchangeRequestsOnly,\r\n\t\t\t\t\t\tincludeAllRelatedOrgApps,\r\n\t\t\t\t\t),\r\n\t\t\t\t);\r\n\t\t\tsetCreatedByCurrentUserOnly(createdByCurrentUserChecked);\r\n\t\t},\r\n\t\t[changeRequestsOnly, includeAllRelatedOrgApps, onNumFiltersAppliedUpdate],\r\n\t);\r\n\r\n\tconst handleChangeRequestsOnlyChecked = useCallback(\r\n\t\t(ev: ChangeEvent<HTMLInputElement>) => {\r\n\t\t\tconst changeRequestsOnlyChecked = ev.target.checked;\r\n\t\t\tonNumFiltersAppliedUpdate &&\r\n\t\t\t\tonNumFiltersAppliedUpdate(\r\n\t\t\t\t\tgetNumFiltersApplied(\r\n\t\t\t\t\t\tcreatedByCurrentUserOnly,\r\n\t\t\t\t\t\tchangeRequestsOnlyChecked,\r\n\t\t\t\t\t\tincludeAllRelatedOrgApps,\r\n\t\t\t\t\t),\r\n\t\t\t\t);\r\n\t\t\tsetChangeRequestsOnly(changeRequestsOnlyChecked);\r\n\t\t},\r\n\t\t[createdByCurrentUserOnly, includeAllRelatedOrgApps, onNumFiltersAppliedUpdate],\r\n\t);\r\n\r\n\tconst handleIncludeAllRelatedOrgAppsChecked = useCallback(\r\n\t\t(ev: ChangeEvent<HTMLInputElement>) => {\r\n\t\t\tconst includeAllRelatedOrgApps = ev.target.checked;\r\n\t\t\tonNumFiltersAppliedUpdate &&\r\n\t\t\t\tonNumFiltersAppliedUpdate(\r\n\t\t\t\t\tgetNumFiltersApplied(\r\n\t\t\t\t\t\tcreatedByCurrentUserOnly,\r\n\t\t\t\t\t\tchangeRequestsOnly,\r\n\t\t\t\t\t\tincludeAllRelatedOrgApps,\r\n\t\t\t\t\t),\r\n\t\t\t\t);\r\n\t\t\tsetIncludeAllRelatedOrgApps(includeAllRelatedOrgApps);\r\n\t\t},\r\n\t\t[createdByCurrentUserOnly, changeRequestsOnly, onNumFiltersAppliedUpdate],\r\n\t);\r\n\r\n\tconst baseUrl = useMemo(() => getBaseUrl(), []);\r\n\tconst entriesPerPage = config.Dashboard.WidgetAppRowsPerPage;\r\n\tconst dispatch = useDispatch();\r\n\r\n\tconst hasLoaded = useHomegrownAppsState((selectors) => selectors.getHasLoaded(orgId), [orgId]);\r\n\r\n\tconst searchParams = {\r\n\t\torgId,\r\n\t\tsearchTerm,\r\n\t\tcurrentUserId: userSecurity.userId!,\r\n\t\tcreatedByCurrentUserOnly,\r\n\t\tchangeRequestsOnly,\r\n\t\tincludeAllRelatedOrgApps,\r\n\t};\r\n\r\n\tconst draftApps = useHomegrownAppsState((selectors) => selectors.getDraftApps(searchParams), [\r\n\t\tsearchParams,\r\n\t]);\r\n\r\n\tconst activatedForTesting = useHomegrownAppsState(\r\n\t\t(selectors) => selectors.getAppsActivatedForTesting(searchParams),\r\n\t\t[searchParams],\r\n\t);\r\n\r\n\tconst activatedForProd = useHomegrownAppsState(\r\n\t\t(selectors) => selectors.getAppsActivatedForProd(searchParams),\r\n\t\t[searchParams],\r\n\t);\r\n\r\n\tconst currentEpicVersion = useHomegrownAppsState(\r\n\t\t(selectors) => selectors.getOrgCurrentEpicVersion(orgId),\r\n\t\t[orgId],\r\n\t);\r\n\r\n\tconst isLocalJKUWarningEnabledForFeb24 = useHomegrownAppsState(\r\n\t\t(selectors) => selectors.getIsLocalJKUWarningEnabledForFeb24(),\r\n\t\t[],\r\n\t);\r\n\r\n\tconst handleAppsLoadedSuccess = useCallback<ISuccessHandler<typeof getHomegrownApps>>(\r\n\t\t(response, extras) => {\r\n\t\t\tconst [orgId] = extras.params;\r\n\t\t\tupdateAppsAfterLoad(\r\n\t\t\t\tdispatch,\r\n\t\t\t\torgId,\r\n\t\t\t\tresponse.homegrownApps,\r\n\t\t\t\tresponse.orgCurrentEpicVersion,\r\n\t\t\t\tresponse.isLocalJKUWarningEnabledForFeb24,\r\n\t\t\t);\r\n\t\t},\r\n\t\t[dispatch],\r\n\t);\r\n\r\n\tconst [LoadingPlaceholder, loadApps] = useAsync(getHomegrownApps, AsyncPlaceholder, {\r\n\t\texecuteImmediately: false,\r\n\t\tdisplayName: \"getHomegrownApps\",\r\n\t\t// `extras` will contain `params` field which has the params passed to getInProgressApps (namely the org ID)\r\n\t\t// this is needed rather than using the orgId from props directly in handleAppsLoaded because\r\n\t\t// that will result in a stale closure (https://gitlab.epic.com/foundations/react-async-hook/-/issues/2)\r\n\t\tonSuccess: (response, extras) => handleAppsLoadedSuccess(response, extras),\r\n\t});\r\n\r\n\tconst filters = useMemo(\r\n\t\t() => (\r\n\t\t\t<>\r\n\t\t\t\t{userSecurity.isEpicCustomer && (\r\n\t\t\t\t\t<Checkbox\r\n\t\t\t\t\t\tisChecked={createdByCurrentUserOnly}\r\n\t\t\t\t\t\tonChange={handleCreatedByCurrentUserChecked}\r\n\t\t\t\t\t\tdisplay={isExpanded ? \"inline-flex\" : \"flex\"}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\tApps I created\r\n\t\t\t\t\t</Checkbox>\r\n\t\t\t\t)}\r\n\t\t\t\t<Checkbox\r\n\t\t\t\t\tisChecked={changeRequestsOnly}\r\n\t\t\t\t\tonChange={handleChangeRequestsOnlyChecked}\r\n\t\t\t\t\tml={isExpanded && userSecurity.isEpicCustomer ? \"1em\" : undefined}\r\n\t\t\t\t\tdisplay={isExpanded ? \"inline-flex\" : \"flex\"}\r\n\t\t\t\t>\r\n\t\t\t\t\tApps with changes requested\r\n\t\t\t\t</Checkbox>\r\n\t\t\t\t{(userSecurity.isEpicUser || userSecurity.canViewAllRelatedOrgApps) && (\r\n\t\t\t\t\t<Checkbox\r\n\t\t\t\t\t\tisChecked={includeAllRelatedOrgApps}\r\n\t\t\t\t\t\tonChange={handleIncludeAllRelatedOrgAppsChecked}\r\n\t\t\t\t\t\tml={isExpanded ? \"1em\" : undefined}\r\n\t\t\t\t\t\tdisplay={isExpanded ? \"inline-flex\" : \"flex\"}\r\n\t\t\t\t\t\ttitle=\"Include all apps created by related customer orgs, even if they haven't been activated. Apps from related customer orgs that have been activated for your system will always show.\"\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\tInclude all related org apps\r\n\t\t\t\t\t</Checkbox>\r\n\t\t\t\t)}\r\n\t\t\t</>\r\n\t\t),\r\n\t\t[\r\n\t\t\tchangeRequestsOnly,\r\n\t\t\tcreatedByCurrentUserOnly,\r\n\t\t\thandleChangeRequestsOnlyChecked,\r\n\t\t\thandleCreatedByCurrentUserChecked,\r\n\t\t\thandleIncludeAllRelatedOrgAppsChecked,\r\n\t\t\tincludeAllRelatedOrgApps,\r\n\t\t\tisExpanded,\r\n\t\t\tuserSecurity.canViewAllRelatedOrgApps,\r\n\t\t\tuserSecurity.isEpicCustomer,\r\n\t\t\tuserSecurity.isEpicUser,\r\n\t\t],\r\n\t);\r\n\r\n\tuseEffect(() => {\r\n\t\t// if/when this issue (https://gitlab.epic.com/foundations/react-async-hook/-/issues/3) is fixed\r\n\t\t// we can use !hasLoaded as a executeImmediately param for useAsync instead to be a bit cleaner\r\n\t\tif (!hasLoaded) {\r\n\t\t\tloadApps(orgId);\r\n\t\t}\r\n\r\n\t\t// clear filters if user clicked clear filters button in parent\r\n\t\tif (numFiltersApplied === 0) {\r\n\t\t\tif (changeRequestsOnly) {\r\n\t\t\t\tsetChangeRequestsOnly(false);\r\n\t\t\t}\r\n\t\t\tif (createdByCurrentUserOnly) {\r\n\t\t\t\tsetCreatedByCurrentUserOnly(false);\r\n\t\t\t}\r\n\r\n\t\t\tif (includeAllRelatedOrgApps) {\r\n\t\t\t\tsetIncludeAllRelatedOrgApps(false);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// tell parent we have filters and how many are applied\r\n\t\tonFiltersUpdate && onFiltersUpdate(filters);\r\n\t}, [\r\n\t\thasLoaded,\r\n\t\tloadApps,\r\n\t\torgId,\r\n\t\tnumFiltersApplied,\r\n\t\tchangeRequestsOnly,\r\n\t\tcreatedByCurrentUserOnly,\r\n\t\tonFiltersUpdate,\r\n\t\tfilters,\r\n\t\tincludeAllRelatedOrgApps,\r\n\t]);\r\n\r\n\t//#endregion\r\n\r\n\tconst tabs: ITab[] = [\r\n\t\t{\r\n\t\t\ttabName: \"In Dev\",\r\n\t\t\tcountPrefix: draftApps.length,\r\n\t\t\thelptext:\r\n\t\t\t\t\"Apps created by users from your organization that have not been activated for testing or production.\",\r\n\t\t\tcontent: (\r\n\t\t\t\t<WidgetTable\r\n\t\t\t\t\tnoRecordsMessage=\"No matching apps\"\r\n\t\t\t\t\tentriesPerPage={!isExpanded ? entriesPerPage : undefined}\r\n\t\t\t\t\tisExpanded={isExpanded}\r\n\t\t\t\t>\r\n\t\t\t\t\t{draftApps.map((app) => (\r\n\t\t\t\t\t\t<HomegrownAppRow\r\n\t\t\t\t\t\t\tdispatch={dispatch}\r\n\t\t\t\t\t\t\tapp={app}\r\n\t\t\t\t\t\t\tkey={app.appId}\r\n\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\tbaseUrl={baseUrl}\r\n\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t\torgCurrentEpicVersion={currentEpicVersion || -1}\r\n\t\t\t\t\t\t\tisLocalJKUWarningEnabled={isLocalJKUWarningEnabledForFeb24}\r\n\t\t\t\t\t\t></HomegrownAppRow>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</WidgetTable>\r\n\t\t\t),\r\n\t\t},\r\n\t\t{\r\n\t\t\ttabName: \"In Testing\",\r\n\t\t\tcountPrefix: activatedForTesting.length,\r\n\t\t\thelptext:\r\n\t\t\t\t\"Apps created by users from your organization that are activated for testing in non-production\",\r\n\t\t\tcontent: (\r\n\t\t\t\t<WidgetTable\r\n\t\t\t\t\tnoRecordsMessage=\"No matching apps\"\r\n\t\t\t\t\tentriesPerPage={!isExpanded ? entriesPerPage : undefined}\r\n\t\t\t\t\tisExpanded={isExpanded}\r\n\t\t\t\t>\r\n\t\t\t\t\t{activatedForTesting.map((app) => (\r\n\t\t\t\t\t\t<HomegrownAppRow\r\n\t\t\t\t\t\t\tdispatch={dispatch}\r\n\t\t\t\t\t\t\tapp={app}\r\n\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t\tkey={app.appId}\r\n\t\t\t\t\t\t\tbaseUrl={baseUrl}\r\n\t\t\t\t\t\t\torgCurrentEpicVersion={currentEpicVersion || -1}\r\n\t\t\t\t\t\t\tisLocalJKUWarningEnabled={isLocalJKUWarningEnabledForFeb24}\r\n\t\t\t\t\t\t></HomegrownAppRow>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</WidgetTable>\r\n\t\t\t),\r\n\t\t},\r\n\t\t{\r\n\t\t\ttabName: \"In Production\",\r\n\t\t\tcountPrefix: activatedForProd.length,\r\n\t\t\thelptext: \"Apps created by users from your organization that are activated for Production use\",\r\n\t\t\tcontent: (\r\n\t\t\t\t<WidgetTable\r\n\t\t\t\t\tnoRecordsMessage=\"No matching apps\"\r\n\t\t\t\t\tentriesPerPage={!isExpanded ? entriesPerPage : undefined}\r\n\t\t\t\t\tisExpanded={isExpanded}\r\n\t\t\t\t>\r\n\t\t\t\t\t{activatedForProd.map((app) => (\r\n\t\t\t\t\t\t<HomegrownAppRow\r\n\t\t\t\t\t\t\tdispatch={dispatch}\r\n\t\t\t\t\t\t\tapp={app}\r\n\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t\tkey={app.appId}\r\n\t\t\t\t\t\t\tbaseUrl={baseUrl}\r\n\t\t\t\t\t\t\torgCurrentEpicVersion={currentEpicVersion || -1}\r\n\t\t\t\t\t\t\tisLocalJKUWarningEnabled={isLocalJKUWarningEnabledForFeb24}\r\n\t\t\t\t\t\t></HomegrownAppRow>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</WidgetTable>\r\n\t\t\t),\r\n\t\t},\r\n\t];\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t{isExpanded && ( //show search bar if in expanded/popup mode\r\n\t\t\t\t<SearchInput\r\n\t\t\t\t\tplaceholder=\"Search for apps by app name or client ID\"\r\n\t\t\t\t\tonChangeCallback={handleChangeSearchTerm}\r\n\t\t\t\t\tinputGroupProps={{ mb: \"1rem\" }}\r\n\t\t\t\t></SearchInput>\r\n\t\t\t)}\r\n\t\t\t<LoadingPlaceholder\r\n\t\t\t\tinProgressIndicator={<WidgetSpinner />}\r\n\t\t\t\terrorMessage=\"Error loading apps from the server\"\r\n\t\t\t\tuseLastRequestForErrors\r\n\t\t\t>\r\n\t\t\t\t{isExpanded && (\r\n\t\t\t\t\t<>\r\n\t\t\t\t\t\t<Box mb=\"0.75em\">\r\n\t\t\t\t\t\t\t<Text as=\"span\" mr=\"0.5em\">\r\n\t\t\t\t\t\t\t\tFilter on:{\" \"}\r\n\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t{filters}\r\n\t\t\t\t\t\t</Box>\r\n\t\t\t\t\t</>\r\n\t\t\t\t)}\r\n\t\t\t\t<TabbedSection tabs={tabs} />\r\n\t\t\t</LoadingPlaceholder>\r\n\t\t</>\r\n\t);\r\n};\r\n\r\nHomegrownAppsWidget.descriptor = \"homegrownApps\";\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file state/store for in progress apps widget\r\n * @module Epic.AppOrchard.State.InProgressApps\r\n */\r\n\r\nimport { buildSharedState } from \"@epic/react-redux-booster\";\r\nimport { DownloadApprovedStatus, InstallStatus } from \"ao/data\";\r\nimport store from \"ao/store\";\r\nimport { IInProgressApp } from \"ao/types\";\r\nimport { searchHasMatch } from \"ao/utils/helpers\";\r\n\r\n/// TYPES ///\r\n\r\nexport interface IState {\r\n\t// Map between the org ID and the in progress apps for a customer org\r\n\treadonly appsForOrg: Map<number, IInProgressApp[]> | undefined;\r\n\t// Whether app data has been loaded for a customer org\r\n\treadonly hasLoadedForOrg: Map<number, boolean> | undefined;\r\n}\r\n\r\n/**\r\n * Search params to identify the apps to select from the store\r\n */\r\ninterface IAppsSelectorParams {\r\n\torgId: number;\r\n\tsearchTerm: string;\r\n}\r\n\r\n/// INIT ///\r\n\r\n/**\r\n * Returns an empty initial state\r\n */\r\nexport function getInitialState(): IState {\r\n\treturn {\r\n\t\thasLoadedForOrg: undefined,\r\n\t\tappsForOrg: undefined,\r\n\t};\r\n}\r\n\r\n//#region REDUCERS\r\n\r\n/**\r\n * Make JS Date objects from string dates loaded from the server\r\n * @param app app to transform\r\n * @returns app with JS Date objects\r\n */\r\nfunction makeJSDates(app: IInProgressApp): IInProgressApp {\r\n\treturn {\r\n\t\t...app,\r\n\t\tdownloadRequest: {\r\n\t\t\tuserName: app.downloadRequest.userName,\r\n\t\t\tinstant: new Date(app.downloadRequest.instant),\r\n\t\t},\r\n\t\tnonProdLicensedOn: app.nonProdLicensedOn && new Date(app.nonProdLicensedOn),\r\n\t\tprodLicensedOn: app.prodLicensedOn && new Date(app.prodLicensedOn),\r\n\t};\r\n}\r\n\r\n/**\r\n * Update in progress apps for a customer org and mark in progress apps as loaded from server\r\n * @param state current state\r\n * @param params reducer params (org ID and apps to add)\r\n * @returns updated state\r\n */\r\nexport function updateAppsAfterLoad(\r\n\tstate: IState,\r\n\tparams: { orgId: number; apps: IInProgressApp[] },\r\n): IState {\r\n\tconst { orgId, apps } = params;\r\n\r\n\t// update state to indicate we've loaded data for this org\r\n\tvar loadedMap = state.hasLoadedForOrg\r\n\t\t? new Map<number, boolean>([...Array.from(state.hasLoadedForOrg), [orgId, true]])\r\n\t\t: new Map<number, boolean>([[orgId, true]]);\r\n\r\n\tconst appsEntryForOrg = apps.map((a) => makeJSDates(a));\r\n\r\n\t// update data loaded for the org\r\n\tconst appsMap = state.appsForOrg\r\n\t\t? new Map<number, IInProgressApp[]>([...Array.from(state.appsForOrg), [orgId, appsEntryForOrg]])\r\n\t\t: new Map<number, IInProgressApp[]>([[orgId, appsEntryForOrg]]);\r\n\r\n\treturn {\r\n\t\thasLoadedForOrg: loadedMap,\r\n\t\tappsForOrg: appsMap,\r\n\t};\r\n}\r\n\r\n/**\r\n * Add or update not implementing now details\r\n * @param state current state\r\n * @param params reducer params (customer org ID and apps to add)\r\n * @returns updated state\r\n */\r\nexport function updateInstallStatus(\r\n\tstate: IState,\r\n\tparams: { appId: number; orgId: number; newStatus: InstallStatus },\r\n): IState {\r\n\tconst { appId, orgId, newStatus } = params;\r\n\tconst currentApps = getAppsOfType(state, orgId, \"\", undefined);\r\n\tconst updatedApps = currentApps.map((app) =>\r\n\t\tapp.appId !== appId ? app : { ...app, installStatus: newStatus },\r\n\t);\r\n\r\n\treturn {\r\n\t\thasLoadedForOrg: state.hasLoadedForOrg,\r\n\t\tappsForOrg: new Map<number, IInProgressApp[]>([\r\n\t\t\t...Array.from(state.appsForOrg!),\r\n\t\t\t[orgId, updatedApps],\r\n\t\t]),\r\n\t};\r\n}\r\n\r\n/**\r\n * Add requested app after customer requests download\r\n * @param state current state\r\n * @param params reducer params (org ID and apps to add)\r\n * @returns updated state\r\n */\r\nexport function addRequestedApp(state: IState, params: { orgId: number; app: IInProgressApp }): IState {\r\n\tconst { orgId, app } = params;\r\n\r\n\tif (!getHasLoaded(state, orgId) || !hasDataForOrg(state, orgId)) {\r\n\t\treturn state;\r\n\t}\r\n\r\n\tconst appsForOrg = getAppsOfType(state, orgId, \"\", undefined);\r\n\tconst appToAdd = makeJSDates(app);\r\n\tconst appsEntryForOrg = [...appsForOrg, appToAdd];\r\n\r\n\t// update data loaded for the org\r\n\tconst appsMap = new Map<number, IInProgressApp[]>([\r\n\t\t...Array.from(state.appsForOrg!),\r\n\t\t[orgId, appsEntryForOrg],\r\n\t]);\r\n\r\n\treturn {\r\n\t\thasLoadedForOrg: state.hasLoadedForOrg,\r\n\t\tappsForOrg: appsMap,\r\n\t};\r\n}\r\n\r\n//#endregion\r\n\r\n//#region SELECTORS\r\n\r\n/**\r\n * Check whether data has been loaded for a customer org\r\n * @param state current state\r\n * @param orgId: customer org id\r\n * @returns\r\n */\r\nexport function getHasLoaded(state: IState, orgId: number): boolean {\r\n\treturn state.hasLoadedForOrg !== undefined && state.hasLoadedForOrg.get(orgId) === true;\r\n}\r\n\r\nfunction hasDataForOrg(state: IState, orgId: number): boolean {\r\n\treturn state.appsForOrg !== undefined && state.appsForOrg.get(orgId) !== undefined;\r\n}\r\n\r\n/**\r\n * Helper to filter apps by search term\r\n * @param searchTerm search term to filter apps on\r\n * @param app app being considered for inclusion in results\r\n * @returns true if passes filter else false\r\n */\r\nfunction filterBySearchTerm(searchTerm: string, app: IInProgressApp): boolean {\r\n\treturn (\r\n\t\tsearchHasMatch(searchTerm, app.appName) ||\r\n\t\tsearchHasMatch(searchTerm, app.appOrgName) ||\r\n\t\tsearchHasMatch(searchTerm, app.prodClientId) ||\r\n\t\tsearchHasMatch(searchTerm, app.nonProdClientId)\r\n\t);\r\n}\r\n\r\n/**\r\n * Shared helper that filters to apps of a given type + search term filtering\r\n *\r\n * Checks if data has been loaded for the org too\r\n * @param state current state\r\n * @param orgId customer org ID\r\n * @param searchTerm search term to further filter matching apps\r\n * @param filterFn function to filter to type of app\r\n * @returns list of apps matching filters\r\n */\r\nfunction getAppsOfType(\r\n\tstate: IState,\r\n\torgId: number,\r\n\tsearchTerm: string,\r\n\tfilterFn: ((app: IInProgressApp) => boolean) | undefined,\r\n): IInProgressApp[] {\r\n\tif (!getHasLoaded(state, orgId) || !hasDataForOrg(state, orgId)) {\r\n\t\treturn [];\r\n\t}\r\n\tlet apps = state.appsForOrg!.get(orgId)!;\r\n\tif (filterFn && apps.length > 0) {\r\n\t\tapps = apps.filter(filterFn);\r\n\t}\r\n\r\n\tif (searchTerm && apps.length > 0) {\r\n\t\tapps = apps.filter((a) => filterBySearchTerm(searchTerm, a));\r\n\t}\r\n\r\n\treturn apps;\r\n}\r\n\r\n/**\r\n * Get download request apps for a customer that are waiting on vendor approval\r\n * @param state current state\r\n * @param params filter params\r\n */\r\nexport function getWaitingOnVendorApps(state: IState, params: IAppsSelectorParams): IInProgressApp[] {\r\n\tconst { orgId, searchTerm } = params;\r\n\tconst apps = getAppsOfType(\r\n\t\tstate,\r\n\t\torgId,\r\n\t\tsearchTerm,\r\n\t\t(a) => a.downloadApprovedStatus === DownloadApprovedStatus.Unapproved,\r\n\t);\r\n\treturn apps.sort((a, b) => a.appName.localeCompare(b.appName));\r\n}\r\n\r\n/**\r\n * Get download request apps for a customer that have the download request approved by the vendor\r\n * \tbut the install has not started yet\r\n * @param state current state\r\n * @param params filter params\r\n */\r\nexport function getNotStartedApps(state: IState, params: IAppsSelectorParams): IInProgressApp[] {\r\n\tconst { orgId, searchTerm } = params;\r\n\tconst apps = getAppsOfType(\r\n\t\tstate,\r\n\t\torgId,\r\n\t\tsearchTerm,\r\n\t\t(a) =>\r\n\t\t\t(a.downloadApprovedStatus === DownloadApprovedStatus.Approved ||\r\n\t\t\t\ta.downloadApprovedStatus === DownloadApprovedStatus.NonProdOnly) &&\r\n\t\t\t(a.installStatus === null || a.installStatus === InstallStatus.NotStarted),\r\n\t);\r\n\treturn apps.sort((a, b) => a.appName.localeCompare(b.appName));\r\n}\r\n\r\n/**\r\n * Get download request apps for a customer that are marked as in progress/implementing\r\n * \tbut the install has not started yet\r\n * @param state current state\r\n * @param params filter params\r\n */\r\nexport function getImplementingApps(state: IState, params: IAppsSelectorParams): IInProgressApp[] {\r\n\tconst { orgId, searchTerm } = params;\r\n\tconst apps = getAppsOfType(\r\n\t\tstate,\r\n\t\torgId,\r\n\t\tsearchTerm,\r\n\t\t(a) =>\r\n\t\t\t(a.downloadApprovedStatus === DownloadApprovedStatus.Approved ||\r\n\t\t\t\ta.downloadApprovedStatus === DownloadApprovedStatus.NonProdOnly) &&\r\n\t\t\ta.installStatus === InstallStatus.InProgress,\r\n\t);\r\n\treturn apps.sort((a, b) => a.appName.localeCompare(b.appName));\r\n}\r\n\r\n//#endregion\r\n\r\n/// BUILD IT ///\r\n\r\nconst builtState = buildSharedState({\r\n\tinit: getInitialState,\r\n\treducers: {\r\n\t\tupdateAppsAfterLoad,\r\n\t\tupdateInstallStatus,\r\n\t\taddRequestedApp,\r\n\t},\r\n\tselectors: {\r\n\t\tgetHasLoaded,\r\n\t\tgetNotStartedApps,\r\n\t\tgetWaitingOnVendorApps,\r\n\t\tgetImplementingApps,\r\n\t},\r\n});\r\nstore.addSharedState(builtState.sharedState, \"inProgressApps\");\r\n\r\nexport const { actionCreators: inProgressAppsActions, useSharedState: useInProgressAppsState } = builtState;\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file state/store for in progress apps widget\r\n * @module Epic.AppOrchard.State.InProgressApps\r\n */\r\n\r\nimport { buildSharedState } from \"@epic/react-redux-booster\";\r\nimport store from \"ao/store\";\r\nimport { ILiveApp } from \"ao/types\";\r\nimport { searchHasMatch } from \"ao/utils/helpers\";\r\n\r\n/// TYPES ///\r\n\r\nexport interface IState {\r\n\t// Map between the org ID and the in apps for a customer org\r\n\treadonly appsForOrg: Map<number, ILiveApp[]> | undefined;\r\n\t// Whether app data has been loaded for a customer org\r\n\treadonly hasLoadedForOrg: Map<number, boolean> | undefined;\r\n}\r\n\r\n/**\r\n * Search params to identify the apps to select from the store\r\n */\r\ninterface IAppsSelectorParams {\r\n\torgId: number;\r\n\tsearchTerm: string;\r\n}\r\n\r\n/// INIT ///\r\n\r\n/**\r\n * Returns an empty initial state\r\n */\r\nexport function getInitialState(): IState {\r\n\treturn {\r\n\t\thasLoadedForOrg: undefined,\r\n\t\tappsForOrg: undefined,\r\n\t};\r\n}\r\n\r\n//#region REDUCERS\r\n\r\n/**\r\n * Make JS Date objects from string dates loaded from the server\r\n * @param app app to transform\r\n * @returns app with JS Date objects\r\n */\r\nfunction makeJSDates(app: ILiveApp): ILiveApp {\r\n\treturn {\r\n\t\t...app,\r\n\t\tmarkedLiveOn: app.markedLiveOn && new Date(app.markedLiveOn),\r\n\t};\r\n}\r\n\r\n/**\r\n * Update in progress apps for a customer org and mark apps as loaded from server\r\n * @param state current state\r\n * @param params reducer params (org ID and apps to add)\r\n * @returns updated state\r\n */\r\nexport function updateAppsAfterLoad(state: IState, params: { orgId: number; apps: ILiveApp[] }): IState {\r\n\tconst { orgId, apps } = params;\r\n\r\n\t// update state to indicate we've loaded data for this org\r\n\tvar loadedMap = state.hasLoadedForOrg\r\n\t\t? new Map<number, boolean>([...Array.from(state.hasLoadedForOrg), [orgId, true]])\r\n\t\t: new Map<number, boolean>([[orgId, true]]);\r\n\r\n\tconst appsEntryForOrg = apps.map((a) => makeJSDates(a));\r\n\r\n\t// update data loaded for the org\r\n\tconst appsMap = state.appsForOrg\r\n\t\t? new Map<number, ILiveApp[]>([...Array.from(state.appsForOrg), [orgId, appsEntryForOrg]])\r\n\t\t: new Map<number, ILiveApp[]>([[orgId, appsEntryForOrg]]);\r\n\r\n\treturn {\r\n\t\thasLoadedForOrg: loadedMap,\r\n\t\tappsForOrg: appsMap,\r\n\t};\r\n}\r\n/**\r\n * Clear loaded flag to force components to reload apps from server,\r\n * @param state current state\r\n * @param params reducer params (org ID)\r\n * @returns updated state\r\n */\r\nexport function clearLoaded(state: IState, orgId: number): IState {\r\n\tif (!getHasLoaded(state, orgId) || !hasDataForOrg(state, orgId)) {\r\n\t\treturn state;\r\n\t}\r\n\r\n\t// remove this org's entry\r\n\tconst appsMap = new Map<number, ILiveApp[]>([\r\n\t\t...Array.from(state.appsForOrg!)\r\n\t\t\t// first entry is org ID for a given map key value pair\r\n\t\t\t.filter((appsForOrg) => appsForOrg[0] !== orgId),\r\n\t]);\r\n\tconst loadedMap = new Map<number, boolean>([\r\n\t\t...Array.from(state.hasLoadedForOrg!).filter((loadedForOrg) => loadedForOrg[0] !== orgId),\r\n\t]);\r\n\r\n\treturn {\r\n\t\thasLoadedForOrg: loadedMap,\r\n\t\tappsForOrg: appsMap,\r\n\t};\r\n}\r\n\r\n//#endregion\r\n\r\n//#region SELECTORS\r\n\r\n/**\r\n * Check whether data has been loaded for a customer org\r\n * @param state current state\r\n * @param orgId: customer org id\r\n * @returns\r\n */\r\nexport function getHasLoaded(state: IState, orgId: number): boolean {\r\n\treturn state.hasLoadedForOrg !== undefined && state.hasLoadedForOrg.get(orgId) === true;\r\n}\r\n\r\nfunction hasDataForOrg(state: IState, orgId: number): boolean {\r\n\treturn state.appsForOrg !== undefined && state.appsForOrg.get(orgId) !== undefined;\r\n}\r\n\r\n/**\r\n * Helper to filter apps by search term\r\n * @param searchTerm search term to filter apps on\r\n * @param app app being considered for inclusion in results\r\n * @returns true if passes filter else false\r\n */\r\nfunction filterBySearchTerm(searchTerm: string, app: ILiveApp): boolean {\r\n\treturn (\r\n\t\tsearchHasMatch(searchTerm, app.appName) ||\r\n\t\tsearchHasMatch(searchTerm, app.appOrgName) ||\r\n\t\tsearchHasMatch(searchTerm, app.prodClientId) ||\r\n\t\tsearchHasMatch(searchTerm, app.nonProdClientId)\r\n\t);\r\n}\r\n\r\n/**\r\n * Shared helper that filters to apps of a given type + search term filtering\r\n *\r\n * Checks if data has been loaded for the org too\r\n * @param state current state\r\n * @param orgId customer org ID\r\n * @param searchTerm search term to further filter matching apps\r\n * @param filterFn function to filter to type of app\r\n * @returns list of apps matching filters\r\n */\r\nfunction getAppsOfType(\r\n\tstate: IState,\r\n\torgId: number,\r\n\tsearchTerm: string,\r\n\tfilterFn: ((app: ILiveApp) => boolean) | undefined,\r\n): ILiveApp[] {\r\n\tif (!getHasLoaded(state, orgId) || !hasDataForOrg(state, orgId)) {\r\n\t\treturn [];\r\n\t}\r\n\tlet apps = state.appsForOrg!.get(orgId)!;\r\n\tif (filterFn && apps.length > 0) {\r\n\t\tapps = apps.filter(filterFn);\r\n\t}\r\n\r\n\tif (searchTerm && apps.length > 0) {\r\n\t\tapps = apps.filter((a) => filterBySearchTerm(searchTerm, a));\r\n\t}\r\n\r\n\treturn apps;\r\n}\r\n\r\n/**\r\n * Get all live apps\r\n * @param state current state\r\n * @param params filter params\r\n */\r\nexport function getAllApps(state: IState, params: IAppsSelectorParams): ILiveApp[] {\r\n\tconst { orgId, searchTerm } = params;\r\n\tconst apps = getAppsOfType(state, orgId, searchTerm, undefined);\r\n\treturn apps.sort((a, b) => a.appName.localeCompare(b.appName));\r\n}\r\n\r\n/**\r\n * Get apps that don't have reviews for the org yet\r\n * @param state current state\r\n * @param params filter params\r\n */\r\nexport function getAppsWithoutReviews(state: IState, params: IAppsSelectorParams): ILiveApp[] {\r\n\tconst { orgId, searchTerm } = params;\r\n\tconst apps = getAppsOfType(state, orgId, searchTerm, (a) => a.numReviewsForOrg === 0);\r\n\treturn apps.sort((a, b) => a.appName.localeCompare(b.appName));\r\n}\r\n\r\n/**\r\n * Get number of apps that went live in the last X months\r\n * @param state current state\r\n * @param params filter params\r\n */\r\nexport function getNumAppsLiveInLastXMonths(\r\n\tstate: IState,\r\n\tparams: { orgId: number; monthsAgo: number },\r\n): number | undefined {\r\n\tconst { orgId, monthsAgo } = params;\r\n\r\n\tif (!getHasLoaded(state, orgId) || !hasDataForOrg(state, orgId)) {\r\n\t\treturn undefined;\r\n\t}\r\n\r\n\tconst today = new Date();\r\n\tconst xMonthsAgoInst = new Date(\r\n\t\ttoday.getFullYear(),\r\n\t\ttoday.getMonth() - monthsAgo,\r\n\t\ttoday.getDay(),\r\n\t).getTime();\r\n\r\n\tconst apps = getAppsOfType(\r\n\t\tstate,\r\n\t\torgId,\r\n\t\t\"\",\r\n\t\t(a) => a.markedLiveOn !== null && a.markedLiveOn.getTime() >= xMonthsAgoInst,\r\n\t);\r\n\treturn apps.length;\r\n}\r\n\r\n//#endregion\r\n\r\n/// BUILD IT ///\r\n\r\nconst builtState = buildSharedState({\r\n\tinit: getInitialState,\r\n\treducers: {\r\n\t\tupdateAppsAfterLoad,\r\n\t\tclearLoaded,\r\n\t},\r\n\tselectors: {\r\n\t\tgetHasLoaded,\r\n\t\tgetAllApps,\r\n\t\tgetAppsWithoutReviews,\r\n\t\tgetNumAppsLiveInLastXMonths,\r\n\t},\r\n});\r\nstore.addSharedState(builtState.sharedState, \"liveApps\");\r\n\r\nexport const { actionCreators: liveAppsActions, useSharedState: useLiveAppsState } = builtState;\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file Summary of whether the app is approved in non PRD, PRD, or both and when it was marked for each (used by the In Progress Apps widget)\r\n * @module Epic.AppOrchard.Dashboard.DownloadApprovedInfo\r\n */\r\n\r\nimport { CheckIcon } from \"@chakra-ui/icons\";\r\nimport { Box } from \"@chakra-ui/react\";\r\nimport { WidgetTag } from \"ao/components/Dashboard/widgetHelpers\";\r\nimport React, { FC, memo } from \"react\";\r\n\r\ninterface IProps {\r\n\tnonProdLicensedOn: Date | null;\r\n\tprodLicensedOn: Date | null;\r\n\t/** Whether the download is activated in Prod only. This can happen if it was approved for all environments, \r\n\t\tand later on a different version was approved for just non PRD */\r\n\tenabledForProdOnly: boolean;\r\n}\r\n\r\n/** Summary of whether the app is approved in non PRD, PRD, or both and when it was marked for each (used by the In Progress Apps widget) */\r\nexport const DownloadApprovedInfo: FC<IProps> = memo((props: IProps) => {\r\n\tconst { nonProdLicensedOn, prodLicensedOn, enabledForProdOnly } = props;\r\n\r\n\tif (nonProdLicensedOn && !prodLicensedOn) {\r\n\t\treturn (\r\n\t\t\t<WidgetTag\r\n\t\t\t\tlabel=\"Enabled for non-production\"\r\n\t\t\t\ttooltipContent={`Enabled for non-production on ${nonProdLicensedOn.toLocaleDateString()}`}\r\n\t\t\t\ticon={CheckIcon}\r\n\t\t\t></WidgetTag>\r\n\t\t);\r\n\t} else if (nonProdLicensedOn && prodLicensedOn) {\r\n\t\treturn (\r\n\t\t\t<>\r\n\t\t\t\t<WidgetTag\r\n\t\t\t\t\tlabel={enabledForProdOnly ? \"Enabled for production\" : \"Enabled for all environments\"}\r\n\t\t\t\t\ttooltipContent={\r\n\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t{!enabledForProdOnly && (\r\n\t\t\t\t\t\t\t\t<Box>\r\n\t\t\t\t\t\t\t\t\tEnabled for non-production on {nonProdLicensedOn.toLocaleDateString()}\r\n\t\t\t\t\t\t\t\t</Box>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t<Box>Enabled for production on {prodLicensedOn.toLocaleDateString()}</Box>\r\n\t\t\t\t\t\t</>\r\n\t\t\t\t\t}\r\n\t\t\t\t\ticon={CheckIcon}\r\n\t\t\t\t></WidgetTag>\r\n\t\t\t</>\r\n\t\t);\r\n\t} else if (!nonProdLicensedOn && prodLicensedOn) {\r\n\t\t// PRD only => activation was for all kinds of environments at once\r\n\t\treturn (\r\n\t\t\t<WidgetTag\r\n\t\t\t\tlabel={enabledForProdOnly ? \"Enabled for production\" : \"Enabled for all environments\"}\r\n\t\t\t\ttooltipContent={`Enabled for ${\r\n\t\t\t\t\tenabledForProdOnly ? \"production\" : \"all environments\"\r\n\t\t\t\t} on ${prodLicensedOn.toLocaleDateString()}`}\r\n\t\t\t\ticon={CheckIcon}\r\n\t\t\t></WidgetTag>\r\n\t\t);\r\n\t} else {\r\n\t\treturn null;\r\n\t}\r\n});\r\n","/**\r\n * @copyright Copyright 2021-2024 Epic Systems Corporation\r\n * @file One row representing one app in the In Progress Apps widget\r\n * @module Epic.AppOrchard.Dashboard.InProgressAppRow\r\n */\r\n\r\nimport { StarIcon } from \"@chakra-ui/icons\";\r\nimport { Box, Image, List, ListItem } from \"@chakra-ui/react\";\r\nimport { IDispatch } from \"@epic/react-redux-booster\";\r\nimport {\r\n\tContactButton,\r\n\tDownloadBuildIcon,\r\n\tDownloadBuildLink,\r\n\tEditableInstallStatus,\r\n\tImplementationGuideLink,\r\n\tNewVersionLink,\r\n} from \"ao/components/Core\";\r\nimport { badgerAuthor } from \"ao/data\";\r\nimport { DownloadApprovedStatus, InstallStatus } from \"ao/data/types\";\r\nimport { useSiteInfoState } from \"ao/state/siteInfo\";\r\nimport { updateInstallStatusInStore } from \"ao/store-methods/inProgressApps\";\r\nimport { clearLoaded } from \"ao/store-methods/liveApps\";\r\nimport { IInProgressApp, IUserSecurity } from \"ao/types\";\r\nimport React, { FC, memo, useCallback, useState } from \"react\";\r\nimport { WidgetActionButton, WidgetAppRow, WidgetTag } from \"../../../widgetHelpers\";\r\nimport { DownloadApprovedInfo } from \"./DownloadApprovedInfo\";\r\n\r\ninterface InProgressAppRowProps {\r\n\tapp: IInProgressApp;\r\n\tuserSecurity: IUserSecurity;\r\n\tbaseUrl: string;\r\n\torgId: number;\r\n\tdispatch: IDispatch;\r\n}\r\n\r\n/** One row representing one app in the In Progress Apps widget */\r\nexport const InProgressAppRow: FC<InProgressAppRowProps> = memo((props: InProgressAppRowProps) => {\r\n\tconst { userSecurity, app, baseUrl, orgId, dispatch } = props;\r\n\r\n\tconst { siteInfo } = useSiteInfoState((selectors) => selectors.getState(), []);\r\n\r\n\tconst marketplaceUrl = `${siteInfo.showroomUrl}Listing?appId=`;\r\n\tconst downloadUrl = `/Download?id=`;\r\n\t\r\n\tconst tesseractLogo = `${baseUrl}Content/images/Tesseract_Logo.png`;\r\n\tconst isNewestAppVersion = app.appId === app.newestAppVersion;\r\n\tconst isUnapproved = app.downloadApprovedStatus === DownloadApprovedStatus.Unapproved;\r\n\tconst hasTcPackages = app.turboChargerDocumentIds.length > 0;\r\n\tconst hasBottomContent =\r\n\t\t(hasTcPackages && !isUnapproved) || !isNewestAppVersion || app.implementationGuideUrl;\r\n\r\n\tconst downloadPageUrl = (app.isAvailableInGallery ? marketplaceUrl : downloadUrl) + app.appId;\r\n\tconst newestVersionDownloadPageUrl =\r\n\t\t(app.isNewestVersionAvailableInGallery ? marketplaceUrl : downloadUrl) + app.newestAppVersion;\r\n\r\n\t// used to focus the app link after the contact button after contacting since the contact button will be disabled\r\n\tconst [appLinkRef, setAppLinkRef] = useState<React.RefObject<HTMLAnchorElement> | null>(null);\r\n\r\n\tconst handleSetAppLinkRef = useCallback(\r\n\t\t(linkRef: React.RefObject<HTMLAnchorElement> | null) => setAppLinkRef(linkRef),\r\n\t\t[],\r\n\t);\r\n\tconst handleUpdateInstallStatusSuccess = useCallback(\r\n\t\t(newStatus: InstallStatus) => {\r\n\t\t\tupdateInstallStatusInStore(dispatch, app.appId, orgId, newStatus);\r\n\r\n\t\t\t// for live apps widget to reload its apps after this new addition\r\n\t\t\tif (newStatus === InstallStatus.Live) {\r\n\t\t\t\tclearLoaded(dispatch, orgId);\r\n\t\t\t}\r\n\t\t},\r\n\t\t[app.appId, dispatch, orgId],\r\n\t);\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t<WidgetAppRow\r\n\t\t\t\tappId={app.appId}\r\n\t\t\t\tappName={app.appName}\r\n\t\t\t\tsubtitle={<Box title=\"The organization that created this app\">{app.appOrgName}</Box>}\r\n\t\t\t\tlinkUrl={downloadPageUrl}\r\n\t\t\t\tonLinkRefCreated={handleSetAppLinkRef}\r\n\t\t\t\tlinkTitle=\"Open this app's listing\"\r\n\t\t\t\tbelowLogoContent={\r\n\t\t\t\t\t<>\r\n\t\t\t\t\t\t{app.tesseractEnabled && (\r\n\t\t\t\t\t\t\t<Image\r\n\t\t\t\t\t\t\t\tsrc={tesseractLogo}\r\n\t\t\t\t\t\t\t\th=\"18px\"\r\n\t\t\t\t\t\t\t\tw=\"18px\"\r\n\t\t\t\t\t\t\t\ttitle=\"This app is enabled for Tesseract.\"\r\n\t\t\t\t\t\t\t\taria-label=\"This app is enabled for Tesseract\"\r\n\t\t\t\t\t\t\t\talt=\"Tesseract logo\"\r\n\t\t\t\t\t\t\t\tdisplay=\"inline-block\"\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t)}\r\n\r\n\t\t\t\t\t\t{hasTcPackages && <DownloadBuildIcon />}\r\n\t\t\t\t\t</>\r\n\t\t\t\t}\r\n\t\t\t\tadditionalAppInfo={\r\n\t\t\t\t\t<List spacing=\"0.3em\" display=\"inline-block\">\r\n\t\t\t\t\t\t{isUnapproved ? (\r\n\t\t\t\t\t\t\t<ListItem>\r\n\t\t\t\t\t\t\t\t<WidgetTag\r\n\t\t\t\t\t\t\t\t\tlabel=\"Download requested\"\r\n\t\t\t\t\t\t\t\t\ttooltipContent={\r\n\t\t\t\t\t\t\t\t\t\t\"Download requested by \" +\r\n\t\t\t\t\t\t\t\t\t\tapp.downloadRequest.userName +\r\n\t\t\t\t\t\t\t\t\t\t\" on \" +\r\n\t\t\t\t\t\t\t\t\t\tapp.downloadRequest.instant.toLocaleDateString()\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\ticon={StarIcon}\r\n\t\t\t\t\t\t\t\t></WidgetTag>\r\n\t\t\t\t\t\t\t</ListItem>\r\n\t\t\t\t\t\t) : (\r\n\t\t\t\t\t\t\t<ListItem>\r\n\t\t\t\t\t\t\t\t<DownloadApprovedInfo\r\n\t\t\t\t\t\t\t\t\tnonProdLicensedOn={app.nonProdLicensedOn}\r\n\t\t\t\t\t\t\t\t\tprodLicensedOn={app.prodLicensedOn}\r\n\t\t\t\t\t\t\t\t\tenabledForProdOnly={app.enabledForProdOnly || false}\r\n\t\t\t\t\t\t\t\t></DownloadApprovedInfo>\r\n\t\t\t\t\t\t\t</ListItem>\r\n\t\t\t\t\t\t)}\r\n\t\t\t\t\t</List>\r\n\t\t\t\t}\r\n\t\t\t\tbottomContent={\r\n\t\t\t\t\thasBottomContent && (\r\n\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t{app.implementationGuideUrl && (\r\n\t\t\t\t\t\t\t\t<ImplementationGuideLink url={app.implementationGuideUrl} />\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t{hasTcPackages && !isUnapproved && (\r\n\t\t\t\t\t\t\t\t<DownloadBuildLink appId={app.appId} showIcon></DownloadBuildLink>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t{!isNewestAppVersion && (\r\n\t\t\t\t\t\t\t\t<NewVersionLink\r\n\t\t\t\t\t\t\t\t\tnewVersionUrl={newestVersionDownloadPageUrl}\r\n\t\t\t\t\t\t\t\t\tshowWarningIcon\r\n\t\t\t\t\t\t\t\t\tappId={app.appId}\r\n\t\t\t\t\t\t\t\t\tnewestAppId={app.newestAppVersion!}\r\n\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t</>\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t\tactions={\r\n\t\t\t\t\tuserSecurity.canPurchase && (\r\n\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t{isUnapproved && (\r\n\t\t\t\t\t\t\t\t<ContactButton\r\n\t\t\t\t\t\t\t\t\tbuttonAs={WidgetActionButton}\r\n\t\t\t\t\t\t\t\t\tcontactApi={badgerAuthor}\r\n\t\t\t\t\t\t\t\t\tapiArgs={[app.appId]}\r\n\t\t\t\t\t\t\t\t\tbuttonCaption=\"Request Update\"\r\n\t\t\t\t\t\t\t\t\ttitle={`Request Update from ${app.appOrgName ?? app.appName}`}\r\n\t\t\t\t\t\t\t\t\tbuttonNotContactedHelptext=\"Send an email to the vendor requesting an update on your pending download request.\"\r\n\t\t\t\t\t\t\t\t\tsuccessMessage=\"An email was sent to the vendor.\"\r\n\t\t\t\t\t\t\t\t\terrorMessage=\"Error contacting the vendor. Please try again later or contact your Epic representative if this continues to happen.\"\r\n\t\t\t\t\t\t\t\t\tconfirmModalTitle={`Request Update from ${app.appOrgName ?? app.appName}`}\r\n\t\t\t\t\t\t\t\t\tconfirmModalPrompt={`This will send an email to ${\r\n\t\t\t\t\t\t\t\t\t\tapp.appOrgName ?? app.appName\r\n\t\t\t\t\t\t\t\t\t} requesting an update on your pending download request. Are you sure you want to continue?`}\r\n\t\t\t\t\t\t\t\t\tfinalFocusRef={appLinkRef || undefined}\r\n\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t<EditableInstallStatus\r\n\t\t\t\t\t\t\t\t\tsuccessHandler={handleUpdateInstallStatusSuccess}\r\n\t\t\t\t\t\t\t\t\tinstallStatus={app.installStatus}\r\n\t\t\t\t\t\t\t\t\tdownloadApprovedStatus={app.downloadApprovedStatus}\r\n\t\t\t\t\t\t\t\t\tappId={app.appId}\r\n\t\t\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\t\t\tbuttonsAs={WidgetActionButton}\r\n\t\t\t\t\t\t\t\t\tdeactivationWarning=\"Are you sure you want to set the install status for this app to deactivated? If you continue the app will be removed from this dashboard. You will still be able to find the app and update the install status from Picked Apps and from the app's listing.\"\r\n\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t</>\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t></WidgetAppRow>\r\n\t\t</>\r\n\t);\r\n});\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file in progress apps store updater methods\r\n * @module Epic.AppOrchard.StoreMethods.InProgressApps\r\n */\r\n\r\nimport { IDispatch } from \"@epic/react-redux-booster\";\r\nimport { InstallStatus } from \"ao/data\";\r\nimport { inProgressAppsActions } from \"ao/state/widgets/inProgressApps\";\r\nimport { IInProgressApp } from \"ao/types\";\r\n\r\n/**\r\n * Update store with in progress apps after loading from server\r\n * @param dispatch for useDispatch\r\n * @param orgId customer org id\r\n * @param apps in progress apps for customer org\r\n */\r\nexport function updateAppsAfterLoad(dispatch: IDispatch, orgId: number, apps: IInProgressApp[]) {\r\n\tdispatch(inProgressAppsActions.updateAppsAfterLoad({ orgId, apps }));\r\n}\r\n\r\n/**\r\n * Update an app's install status\r\n * @param dispatch for useDispatch\r\n * @param appId client app id\r\n * @param orgId customer org id\r\n * @param newStatus new install status\r\n */\r\nexport function updateInstallStatusInStore(\r\n\tdispatch: IDispatch,\r\n\tappId: number,\r\n\torgId: number,\r\n\tnewStatus: InstallStatus,\r\n) {\r\n\tdispatch(inProgressAppsActions.updateInstallStatus({ appId, orgId, newStatus }));\r\n}\r\n\r\n/**\r\n * Add a newly requested app to the store\r\n * @param dispatch for useDispatch\r\n * @param orgId customer org id\r\n * @param app the app the was requested\r\n */\r\nexport function addRequestedApp(dispatch: IDispatch, orgId: number, app: IInProgressApp) {\r\n\tdispatch(inProgressAppsActions.addRequestedApp({ orgId, app }));\r\n}\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file live apps store updater methods\r\n * @module Epic.AppOrchard.StoreMethods.LiveApps\r\n */\r\n\r\nimport { IDispatch } from \"@epic/react-redux-booster\";\r\nimport { liveAppsActions } from \"ao/state/widgets/liveApps\";\r\nimport { ILiveApp } from \"ao/types\";\r\n\r\n/**\r\n * Update store with apps after loading from server\r\n * @param dispatch for useDispatch\r\n * @param orgId customer org id\r\n * @param apps apps for customer org\r\n */\r\nexport function updateAppsAfterLoad(dispatch: IDispatch, orgId: number, apps: ILiveApp[]) {\r\n\tdispatch(liveAppsActions.updateAppsAfterLoad({ orgId, apps }));\r\n}\r\n\r\n/**\r\n * Clear loaded flag to force components to reload apps from server,\r\n * for example when a new live app is created in another widget\r\n * @param dispatch for useDispatch\r\n * @param orgId customer org id\r\n */\r\nexport function clearLoaded(dispatch: IDispatch, orgId: number) {\r\n\tdispatch(liveAppsActions.clearLoaded(orgId));\r\n}\r\n","/**\r\n * @copyright Copyright 2021-2023 Epic Systems Corporation\r\n * @file In progress apps dashboard widget\r\n * @module Epic.AppOrchard.Dashboard.Widgets.InProgressAppsWidget\r\n */\r\n\r\nimport { ISuccessHandler, useAsync } from \"@epic/react-async-hook\";\r\nimport { useDispatch } from \"@epic/react-redux-booster\";\r\nimport { config } from \"ao/appConfig\";\r\nimport { AsyncPlaceholder, ITab, SearchInput, TabbedSection } from \"ao/components/Core\";\r\nimport { getInProgressApps } from \"ao/components/Dashboard/data\";\r\nimport { useInProgressAppsState } from \"ao/state/widgets/inProgressApps\";\r\nimport { updateAppsAfterLoad } from \"ao/store-methods/inProgressApps\";\r\nimport { IWidget, IWidgetProps } from \"ao/types/dashboard\";\r\nimport { getBaseUrl } from \"ao/utils/helpers\";\r\nimport React, { useCallback, useEffect, useMemo, useState } from \"react\";\r\nimport { WidgetSpinner, WidgetTable } from \"../../widgetHelpers\";\r\nimport { InProgressAppRow } from \"./helperComponents/InProgressAppRow\";\r\n\r\n/** In progress apps dashboard widget */\r\nexport const InProgressAppsWidget: IWidget = (props: IWidgetProps) => {\r\n\t//#region state and props\r\n\r\n\tconst { isExpanded, userSecurity, orgId, onSubtitleUpdate } = props;\r\n\tconst [searchTerm, setSearchTerm] = useState<string>(\"\");\r\n\tconst handleChangeSearchTerm = useCallback((newSearchTerm: string) => setSearchTerm(newSearchTerm), []);\r\n\tconst baseUrl = useMemo(() => getBaseUrl(), []);\r\n\tconst entriesPerPage = config.Dashboard.WidgetAppRowsPerPage;\r\n\r\n\tconst dispatch = useDispatch();\r\n\r\n\tconst hasLoaded = useInProgressAppsState((selectors) => selectors.getHasLoaded(orgId), [orgId]);\r\n\r\n\tconst waitingForVendorApps = useInProgressAppsState(\r\n\t\t(selectors) => selectors.getWaitingOnVendorApps({ orgId, searchTerm }),\r\n\t\t[orgId, searchTerm],\r\n\t);\r\n\tconst notStartedApps = useInProgressAppsState(\r\n\t\t(selectors) => selectors.getNotStartedApps({ orgId, searchTerm }),\r\n\t\t[orgId, searchTerm],\r\n\t);\r\n\r\n\tconst implementingApps = useInProgressAppsState(\r\n\t\t(selectors) => selectors.getImplementingApps({ orgId, searchTerm }),\r\n\t\t[orgId, searchTerm],\r\n\t);\r\n\r\n\tconst handleAppsLoaded = useCallback<ISuccessHandler<typeof getInProgressApps>>(\r\n\t\t(response, extras) => {\r\n\t\t\tconst [orgId] = extras.params;\r\n\t\t\tupdateAppsAfterLoad(dispatch, orgId, response.inProgressApps);\r\n\t\t},\r\n\t\t[dispatch],\r\n\t);\r\n\tconst [LoadingPlaceholder, loadApps] = useAsync(getInProgressApps, AsyncPlaceholder, {\r\n\t\texecuteImmediately: false,\r\n\t\tdisplayName: \"getInProgressApps\",\r\n\t\t// `extras` will contain `params` field which has the params passed to getInProgressApps (namely the org ID)\r\n\t\t// this is needed rather than using the orgId from props directly in handleAppsLoaded because\r\n\t\t// that will result in a stale closure (https://gitlab.epic.com/foundations/react-async-hook/-/issues/2)\r\n\t\tonSuccess: (response, extras) => handleAppsLoaded(response, extras),\r\n\t});\r\n\r\n\tuseEffect(() => {\r\n\t\t// if/when this issue (https://gitlab.epic.com/foundations/react-async-hook/-/issues/3) is fixed\r\n\t\t// we can use !hasLoaded as a executeImmediately param for useAsync instead to be a bit cleaner\r\n\t\tif (!hasLoaded) {\r\n\t\t\tloadApps(orgId);\r\n\t\t}\r\n\r\n\t\tonSubtitleUpdate(\"Requested or implementing apps\");\r\n\t}, [hasLoaded, loadApps, onSubtitleUpdate, orgId]);\r\n\r\n\t//#endregion\r\n\r\n\tconst tabs: ITab[] = [\r\n\t\t{\r\n\t\t\ttabName: \"Waiting for Vendor\",\r\n\t\t\tcountPrefix: waitingForVendorApps.length,\r\n\t\t\thelptext: \"Apps that are waiting for vendor to approve the download request\",\r\n\t\t\tcontent: (\r\n\t\t\t\t<WidgetTable\r\n\t\t\t\t\tnoRecordsMessage=\"No matching apps\"\r\n\t\t\t\t\tentriesPerPage={!isExpanded ? entriesPerPage : undefined}\r\n\t\t\t\t\tisExpanded={isExpanded}\r\n\t\t\t\t>\r\n\t\t\t\t\t{waitingForVendorApps.map((app) => (\r\n\t\t\t\t\t\t<InProgressAppRow\r\n\t\t\t\t\t\t\tapp={app}\r\n\t\t\t\t\t\t\tkey={app.appId}\r\n\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t\tbaseUrl={baseUrl}\r\n\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\tdispatch={dispatch}\r\n\t\t\t\t\t\t></InProgressAppRow>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</WidgetTable>\r\n\t\t\t),\r\n\t\t},\r\n\t\t{\r\n\t\t\ttabName: \"Not Started\",\r\n\t\t\tcountPrefix: notStartedApps.length,\r\n\t\t\thelptext: \"Apps with approved download requests that haven't been marked as in progress\",\r\n\t\t\tcontent: (\r\n\t\t\t\t<WidgetTable\r\n\t\t\t\t\tnoRecordsMessage=\"No matching apps\"\r\n\t\t\t\t\tentriesPerPage={!isExpanded ? entriesPerPage : undefined}\r\n\t\t\t\t\tisExpanded={isExpanded}\r\n\t\t\t\t>\r\n\t\t\t\t\t{notStartedApps.map((app) => (\r\n\t\t\t\t\t\t<InProgressAppRow\r\n\t\t\t\t\t\t\tapp={app}\r\n\t\t\t\t\t\t\tkey={app.appId}\r\n\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t\tbaseUrl={baseUrl}\r\n\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\tdispatch={dispatch}\r\n\t\t\t\t\t\t></InProgressAppRow>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</WidgetTable>\r\n\t\t\t),\r\n\t\t},\r\n\t\t{\r\n\t\t\ttabName: \"Implementing\",\r\n\t\t\tcountPrefix: implementingApps.length,\r\n\t\t\thelptext: \"Apps currently being implemented\",\r\n\t\t\tcontent: (\r\n\t\t\t\t<WidgetTable\r\n\t\t\t\t\tnoRecordsMessage=\"No matching apps\"\r\n\t\t\t\t\tentriesPerPage={!isExpanded ? entriesPerPage : undefined}\r\n\t\t\t\t\tisExpanded={isExpanded}\r\n\t\t\t\t>\r\n\t\t\t\t\t{implementingApps.map((app) => (\r\n\t\t\t\t\t\t<InProgressAppRow\r\n\t\t\t\t\t\t\tapp={app}\r\n\t\t\t\t\t\t\tkey={app.appId}\r\n\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t\tbaseUrl={baseUrl}\r\n\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\tdispatch={dispatch}\r\n\t\t\t\t\t\t></InProgressAppRow>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</WidgetTable>\r\n\t\t\t),\r\n\t\t},\r\n\t];\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t{isExpanded && ( //show search bar if in expanded/popup mode\r\n\t\t\t\t<SearchInput\r\n\t\t\t\t\tplaceholder=\"Search for apps by app name, company name, client ID\"\r\n\t\t\t\t\tonChangeCallback={handleChangeSearchTerm}\r\n\t\t\t\t\tinputGroupProps={{ mb: \"1rem\" }}\r\n\t\t\t\t></SearchInput>\r\n\t\t\t)}\r\n\t\t\t<LoadingPlaceholder\r\n\t\t\t\tinProgressIndicator={<WidgetSpinner />}\r\n\t\t\t\terrorMessage=\"Error loading apps from the server\"\r\n\t\t\t\tuseLastRequestForErrors\r\n\t\t\t>\r\n\t\t\t\t<TabbedSection tabs={tabs} />\r\n\t\t\t</LoadingPlaceholder>\r\n\t\t</>\r\n\t);\r\n};\r\n\r\nInProgressAppsWidget.descriptor = \"inProgressApps\";\r\n","/**\r\n * @copyright Copyright 2021-2024 Epic Systems Corporation\r\n * @file One row representing one app in the Live Apps widget\r\n * @module Epic.AppOrchard.Dashboard.LiveAppRow\r\n */\r\n\r\nimport { CheckIcon } from \"@chakra-ui/icons\";\r\nimport { Box, Image, List, ListItem } from \"@chakra-ui/react\";\r\nimport {\r\n\tAOLink,\r\n\tDownloadBuildIcon,\r\n\tDownloadBuildLink,\r\n\tImplementationGuideLink,\r\n\tNewVersionLink,\r\n} from \"ao/components/Core\";\r\nimport { useSiteInfoState } from \"ao/state/siteInfo\";\r\nimport { ILiveApp, IUserSecurity } from \"ao/types\";\r\nimport React, { FC, memo } from \"react\";\r\nimport { ImStatsBars } from \"react-icons/im\";\r\nimport { IoSpeedometerOutline } from \"react-icons/io5\";\r\nimport { VscFeedback } from \"react-icons/vsc\";\r\nimport { WidgetActionButton, WidgetAppBadge, WidgetAppRow, WidgetTag } from \"../../../widgetHelpers\";\r\n\r\ninterface IProps {\r\n\tapp: ILiveApp;\r\n\tuserSecurity: IUserSecurity;\r\n\tbaseUrl: string;\r\n\torgId: number;\r\n\tisGalleryEnabled: boolean | undefined;\r\n}\r\n\r\n/** One row representing one app in the Live Apps widget */\r\nexport const LiveAppRow: FC<IProps> = memo((props: IProps) => {\r\n\tconst { app, userSecurity, baseUrl, orgId, isGalleryEnabled } = props;\r\n\r\n\t//#region state/handlers\r\n\tconst { siteInfo } = useSiteInfoState((selectors) => selectors.getState(), []);\r\n\r\n\tconst marketplaceUrl = `${siteInfo.showroomUrl}Listing?appId=`;\r\n\tconst downloadUrl = `/Download?id=`;\r\n\tconst statsUrl = `${baseUrl}Stats?OrgId=${orgId}&ClientId=${app.prodClientId}`;\r\n\tconst metricsUrl = `${baseUrl}ApiMetrics?OrgId=${orgId}&ClientId=${app.prodClientId}`;\r\n\tconst editReviewUrl = `${baseUrl}Review?id=${app.appId}`;\r\n\tconst tesseractLogo = `${baseUrl}Content/images/Tesseract_Logo.png`;\r\n\tconst viewReviewsUrl = `${baseUrl}Picked?id=${app.appId}&tab=reviews`;\r\n\r\n\tconst isNewestAppVersion = app.appId === app.newestAppVersion;\r\n\tconst hasTcPackages = app.turboChargerDocumentIds.length > 0;\r\n\tconst hasBottomContent =\r\n\t\thasTcPackages ||\r\n\t\t!isNewestAppVersion ||\r\n\t\tapp.implementationGuideUrl ||\r\n\t\tapp.hasApiMetricsForOrg ||\r\n\t\tapp.hasApiStatsForOrg;\r\n\r\n\tlet markedLiveByInfo = \"\";\r\n\tif (app.markedLiveAutomatically) {\r\n\t\tmarkedLiveByInfo = \"automatically based on production API usage\";\r\n\t} else if (app.markedLiveByUserName) {\r\n\t\tmarkedLiveByInfo = \"by \" + app.markedLiveByUserName;\r\n\t}\r\n\tconst markedLiveInfo = app.markedLiveOn\r\n\t\t? `Marked live ${markedLiveByInfo} on ${app.markedLiveOn.toLocaleDateString()}`\r\n\t\t: null;\r\n\tconst reviewsHelptext = `${app.numReviews} total reviews for this app. Click to see all reviews.`;\r\n\r\n\tconst downloadPageUrl = (app.isAvailableInGallery ? marketplaceUrl : downloadUrl) + app.appId;\r\n\tconst newestVersionDownloadPageUrl =\r\n\t\t(app.isNewestVersionAvailableInGallery ? marketplaceUrl : downloadUrl) + app.newestAppVersion;\r\n\r\n\t//#endregion\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t<WidgetAppRow\r\n\t\t\t\tappId={app.appId}\r\n\t\t\t\tappName={app.appName}\r\n\t\t\t\tsubtitle={<Box title=\"The organization that created this app\">{app.appOrgName}</Box>}\r\n\t\t\t\tlinkUrl={downloadPageUrl}\r\n\t\t\t\tlinkTitle=\"Open this app's listing\"\r\n\t\t\t\tbelowLogoContent={\r\n\t\t\t\t\t<>\r\n\t\t\t\t\t\t{app.tesseractEnabled && (\r\n\t\t\t\t\t\t\t<Image\r\n\t\t\t\t\t\t\t\tsrc={tesseractLogo}\r\n\t\t\t\t\t\t\t\th=\"18px\"\r\n\t\t\t\t\t\t\t\tw=\"18px\"\r\n\t\t\t\t\t\t\t\ttitle=\"This app is enabled for Tesseract.\"\r\n\t\t\t\t\t\t\t\taria-label=\"This app is enabled for Tesseract\"\r\n\t\t\t\t\t\t\t\talt=\"Tesseract logo\"\r\n\t\t\t\t\t\t\t\tdisplay=\"inline-block\"\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t)}\r\n\r\n\t\t\t\t\t\t{hasTcPackages && <DownloadBuildIcon />}\r\n\t\t\t\t\t</>\r\n\t\t\t\t}\r\n\t\t\t\tadditionalAppInfo={\r\n\t\t\t\t\t<List spacing=\"0.3em\" display=\"inline-block\">\r\n\t\t\t\t\t\t<ListItem>\r\n\t\t\t\t\t\t\t<WidgetTag\r\n\t\t\t\t\t\t\t\tlabel=\"Live\"\r\n\t\t\t\t\t\t\t\ttooltipContent={markedLiveInfo}\r\n\t\t\t\t\t\t\t\ticon={CheckIcon}\r\n\t\t\t\t\t\t\t></WidgetTag>\r\n\t\t\t\t\t\t</ListItem>\r\n\t\t\t\t\t</List>\r\n\t\t\t\t}\r\n\t\t\t\tmiddleColumnContent={\r\n\t\t\t\t\t//disabled for now\r\n\t\t\t\t\tfalse &&\r\n\t\t\t\t\tapp.numReviews > 0 &&\r\n\t\t\t\t\tisGalleryEnabled && (\r\n\t\t\t\t\t\t<AOLink url={viewReviewsUrl} target=\"_blank\" title={reviewsHelptext}>\r\n\t\t\t\t\t\t\t<WidgetAppBadge title={reviewsHelptext} value={app.numReviews.toString()}>\r\n\t\t\t\t\t\t\t\t<VscFeedback size={20} color=\"darkblue\" style={{ display: \"inline\" }} />\r\n\t\t\t\t\t\t\t</WidgetAppBadge>\r\n\t\t\t\t\t\t</AOLink>\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t\tbottomContent={\r\n\t\t\t\t\thasBottomContent && (\r\n\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t{app.implementationGuideUrl && (\r\n\t\t\t\t\t\t\t\t<ImplementationGuideLink url={app.implementationGuideUrl} />\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t{hasTcPackages && (\r\n\t\t\t\t\t\t\t\t<DownloadBuildLink appId={app.appId} showIcon></DownloadBuildLink>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t{!isNewestAppVersion && (\r\n\t\t\t\t\t\t\t\t<NewVersionLink\r\n\t\t\t\t\t\t\t\t\tappId={app.appId}\r\n\t\t\t\t\t\t\t\t\tnewestAppId={app.newestAppVersion!}\r\n\t\t\t\t\t\t\t\t\tnewVersionUrl={newestVersionDownloadPageUrl}\r\n\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t{app.hasApiStatsForOrg && (\r\n\t\t\t\t\t\t\t\t<AOLink\r\n\t\t\t\t\t\t\t\t\turl={statsUrl}\r\n\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\r\n\t\t\t\t\t\t\t\t\ttitle=\"View stats for API calls this app has made\"\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t<ImStatsBars\r\n\t\t\t\t\t\t\t\t\t\tcolor=\"darkgoldenrod\"\r\n\t\t\t\t\t\t\t\t\t\tstyle={{ display: \"inline\", marginRight: \"4px\" }}\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\tAPI Stats\r\n\t\t\t\t\t\t\t\t</AOLink>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t{app.hasApiMetricsForOrg && (\r\n\t\t\t\t\t\t\t\t<AOLink\r\n\t\t\t\t\t\t\t\t\turl={metricsUrl}\r\n\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\r\n\t\t\t\t\t\t\t\t\ttitle=\"View performance metrics for API calls this app has made\"\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t<IoSpeedometerOutline\r\n\t\t\t\t\t\t\t\t\t\tcolor=\"darkgreen\"\r\n\t\t\t\t\t\t\t\t\t\tstyle={{ display: \"inline\", marginRight: \"4px\" }}\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\tAPI Performance\r\n\t\t\t\t\t\t\t\t</AOLink>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t</>\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t\tactions={\r\n\t\t\t\t\t//disable for now\r\n\t\t\t\t\tfalse &&\r\n\t\t\t\t\tuserSecurity.isEpicCustomer && (\r\n\t\t\t\t\t\t<WidgetActionButton\r\n\t\t\t\t\t\t\tas=\"a\"\r\n\t\t\t\t\t\t\thref={editReviewUrl}\r\n\t\t\t\t\t\t\ttarget=\"_blank\"\r\n\t\t\t\t\t\t\tcolorScheme=\"blue\"\r\n\t\t\t\t\t\t\ttitle={\r\n\t\t\t\t\t\t\t\tapp.currentUserHasReview\r\n\t\t\t\t\t\t\t\t\t? \"Edit your review for this app\"\r\n\t\t\t\t\t\t\t\t\t: \"Add a review for this app\"\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\taria-label={\r\n\t\t\t\t\t\t\t\tapp.currentUserHasReview\r\n\t\t\t\t\t\t\t\t\t? \"Edit your review for this app\"\r\n\t\t\t\t\t\t\t\t\t: \"Add a review for this app\"\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tleftIcon={<VscFeedback size={20} />}\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t{app.currentUserHasReview ? \"Edit Review\" : \"Add Review\"}\r\n\t\t\t\t\t\t</WidgetActionButton>\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t></WidgetAppRow>\r\n\t\t</>\r\n\t);\r\n});\r\n","/**\r\n * @copyright Copyright 2021-2023 Epic Systems Corporation\r\n * @file Live apps dashboard widget\r\n * @module Epic.AppOrchard.Dashboard.Widgets.LiveAppsWidget\r\n */\r\n\r\nimport { ISuccessHandler, useAsync } from \"@epic/react-async-hook\";\r\nimport { useDispatch } from \"@epic/react-redux-booster\";\r\nimport { config } from \"ao/appConfig\";\r\nimport { AsyncPlaceholder, ITab, SearchInput, TabbedSection } from \"ao/components/Core\";\r\nimport { getLiveApps } from \"ao/components/Dashboard/data\";\r\nimport { useSiteInfoState } from \"ao/state/siteInfo\";\r\nimport { useLiveAppsState } from \"ao/state/widgets/liveApps\";\r\nimport { updateAppsAfterLoad } from \"ao/store-methods/liveApps\";\r\nimport { IWidget, IWidgetProps } from \"ao/types/dashboard\";\r\nimport { getBaseUrl } from \"ao/utils/helpers\";\r\nimport React, { useCallback, useEffect, useMemo, useState } from \"react\";\r\nimport { WidgetSpinner, WidgetTable } from \"../../widgetHelpers\";\r\nimport { LiveAppRow } from \"./helperComponents/LiveAppRow\";\r\n\r\n/** Live apps dashboard widget */\r\nexport const LiveAppsWidget: IWidget = (props: IWidgetProps) => {\r\n\t//#region state and props\r\n\r\n\tconst { siteInfo } = useSiteInfoState((selectors) => selectors.getState(), []);\r\n\r\n\tconst { isExpanded, orgId, onSubtitleUpdate, userSecurity } = props;\r\n\tconst [searchTerm, setSearchTerm] = useState<string>(\"\");\r\n\tconst handleChangeSearchTerm = useCallback((newSearchTerm: string) => setSearchTerm(newSearchTerm), []);\r\n\tconst baseUrl = useMemo(() => getBaseUrl(), []);\r\n\tconst entriesPerPage = config.Dashboard.WidgetAppRowsPerPage;\r\n\tconst monthsAgoForLiveAppsHeader = config.Dashboard.MonthsAgoForLiveAppsHeader;\r\n\r\n\tconst dispatch = useDispatch();\r\n\r\n\tconst hasLoaded = useLiveAppsState((selectors) => selectors.getHasLoaded(orgId), [orgId]);\r\n\r\n\tconst allApps = useLiveAppsState((selectors) => selectors.getAllApps({ orgId, searchTerm }), [\r\n\t\torgId,\r\n\t\tsearchTerm,\r\n\t]);\r\n\r\n\tconst numApsLiveInLastXMonths = useLiveAppsState(\r\n\t\t(selectors) =>\r\n\t\t\tselectors.getNumAppsLiveInLastXMonths({ orgId, monthsAgo: monthsAgoForLiveAppsHeader }),\r\n\t\t[orgId],\r\n\t);\r\n\r\n\tconst handleAppsLoadedSuccess = useCallback<ISuccessHandler<typeof getLiveApps>>(\r\n\t\t(response, extras) => {\r\n\t\t\tconst [orgId] = extras.params;\r\n\t\t\tupdateAppsAfterLoad(dispatch, orgId, response.liveApps);\r\n\t\t},\r\n\t\t[dispatch],\r\n\t);\r\n\r\n\tconst [LoadingPlaceholder, loadApps] = useAsync(getLiveApps, AsyncPlaceholder, {\r\n\t\texecuteImmediately: false,\r\n\t\tdisplayName: \"getLiveApps\",\r\n\t\t// `extras` will contain `params` field which has the params passed to getInProgressApps (namely the org ID)\r\n\t\t// this is needed rather than using the orgId from props directly in handleAppsLoaded because\r\n\t\t// that will result in a stale closure (https://gitlab.epic.com/foundations/react-async-hook/-/issues/2)\r\n\t\tonSuccess: (response, extras) => handleAppsLoadedSuccess(response, extras),\r\n\t});\r\n\r\n\tuseEffect(() => {\r\n\t\t// if/when this issue (https://gitlab.epic.com/foundations/react-async-hook/-/issues/3) is fixed\r\n\t\t// we can use !hasLoaded as a executeImmediately param for useAsync instead to be a bit cleaner\r\n\t\tif (!hasLoaded) {\r\n\t\t\tloadApps(orgId);\r\n\t\t}\r\n\t\tif (numApsLiveInLastXMonths !== undefined) {\r\n\t\t\tconst subtitle = `${numApsLiveInLastXMonths} live in the last ${monthsAgoForLiveAppsHeader} months`;\r\n\t\t\tonSubtitleUpdate(subtitle);\r\n\t\t}\r\n\t}, [hasLoaded, loadApps, orgId, numApsLiveInLastXMonths, onSubtitleUpdate, monthsAgoForLiveAppsHeader]);\r\n\r\n\t// //#endregion\r\n\r\n\tconst tabs: ITab[] = [\r\n\t\t{\r\n\t\t\ttabName: \"Live Apps\",\r\n\t\t\tcountPrefix: allApps.length,\r\n\t\t\thelptext: `All live ${config.SiteName} apps`,\r\n\t\t\tcontent: (\r\n\t\t\t\t<WidgetTable\r\n\t\t\t\t\tnoRecordsMessage=\"No matching apps\"\r\n\t\t\t\t\tentriesPerPage={!isExpanded ? entriesPerPage : undefined}\r\n\t\t\t\t\tisExpanded={isExpanded}\r\n\t\t\t\t>\r\n\t\t\t\t\t{allApps.map((app) => (\r\n\t\t\t\t\t\t<LiveAppRow\r\n\t\t\t\t\t\t\tapp={app}\r\n\t\t\t\t\t\t\tkey={app.appId}\r\n\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\tbaseUrl={baseUrl}\r\n\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t\tisGalleryEnabled={siteInfo.isGalleryEnabled}\r\n\t\t\t\t\t\t></LiveAppRow>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</WidgetTable>\r\n\t\t\t),\r\n\t\t},\r\n\t];\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t{isExpanded && ( //show search bar if in expanded/popup mode\r\n\t\t\t\t<SearchInput\r\n\t\t\t\t\tplaceholder=\"Search for apps by app name, company name, client ID\"\r\n\t\t\t\t\tonChangeCallback={handleChangeSearchTerm}\r\n\t\t\t\t\tinputGroupProps={{ mb: \"1rem\" }}\r\n\t\t\t\t></SearchInput>\r\n\t\t\t)}\r\n\t\t\t<LoadingPlaceholder\r\n\t\t\t\tinProgressIndicator={<WidgetSpinner />}\r\n\t\t\t\terrorMessage=\"Error loading apps from the server\"\r\n\t\t\t\tuseLastRequestForErrors\r\n\t\t\t>\r\n\t\t\t\t<TabbedSection tabs={tabs} />\r\n\t\t\t</LoadingPlaceholder>\r\n\t\t</>\r\n\t);\r\n};\r\n\r\nLiveAppsWidget.descriptor = \"liveApps\";\r\n","/**\r\n * @copyright Copyright 2021-2023 Epic Systems Corporation\r\n * @file One row representing one app in the Nominated Apps widget\r\n * @module Epic.AppOrchard.Dashboard.NominatedAppRow\r\n */\r\n\r\nimport {\r\n\tBox,\r\n\tButton,\r\n\tImage,\r\n\tModal,\r\n\tModalBody,\r\n\tModalCloseButton,\r\n\tModalContent,\r\n\tModalFooter,\r\n\tModalHeader,\r\n\tModalOverlay,\r\n\tVStack,\r\n\tWrap,\r\n\tWrapItem,\r\n} from \"@chakra-ui/react\";\r\nimport { IDispatch } from \"@epic/react-redux-booster\";\r\nimport { AOLink, DownloadBuildIcon, ImplementationGuideLink } from \"ao/components/Core\";\r\nimport { EnvironmentType } from \"ao/data\";\r\nimport { INominatedApp, IUserSecurity } from \"ao/types\";\r\nimport React, { FC, memo, useCallback, useState } from \"react\";\r\nimport { VscFeedback } from \"react-icons/vsc\";\r\nimport { NominatedAppsButtons, NominationInfo, NotImplementingNowInfo } from \".\";\r\nimport { WidgetAppBadge, WidgetAppRow } from \"../../../widgetHelpers\";\r\n\r\nfunction getOtherOrgsMessage(totalOrgs: number, numOrgNames: number): string | null {\r\n\tif (totalOrgs > numOrgNames) {\r\n\t\tconst numOtherOrgs = totalOrgs - numOrgNames;\r\n\t\treturn `and ${numOtherOrgs} other organization${numOtherOrgs !== 1 ? \"s\" : \"\"}`;\r\n\t}\r\n\treturn null;\r\n}\r\n\r\ninterface INominatedAppRowProps {\r\n\tapp: INominatedApp;\r\n\tuserSecurity: IUserSecurity;\r\n\tmarketplaceUrl: string;\r\n\tdownloadUrl: string;\r\n\ttesseractLogo: string;\r\n\torgId: number;\r\n\tparticipantTermsId: number | undefined; // undefined while loading\r\n\tdispatch: IDispatch;\r\n\tinstallingLogo: string;\r\n\tliveLogo: string;\r\n\tisGalleryEnabled: boolean | undefined;\r\n}\r\n\r\n/** One row representing one app in the Nominated Apps widget */\r\nexport const NominatedAppRow: FC<INominatedAppRowProps> = memo((props: INominatedAppRowProps) => {\r\n\tconst {\r\n\t\tapp,\r\n\t\tuserSecurity,\r\n\t\tmarketplaceUrl,\r\n\t\tdownloadUrl,\r\n\t\ttesseractLogo,\r\n\t\torgId,\r\n\t\tparticipantTermsId,\r\n\t\tdispatch,\r\n\t\tinstallingLogo,\r\n\t\tliveLogo,\r\n\t\tisGalleryEnabled,\r\n\t} = props;\r\n\r\n\t//#region state/handlers\r\n\t// used to focus the next focusable element after the contact button after contacting since the contact button will be disabled\r\n\tconst [appLinkRef, setAppLinkRef] = useState<React.RefObject<HTMLAnchorElement> | null>(null);\r\n\tconst [showingOrgsModal, setShowingOrgsModal] = useState<boolean>(false);\r\n\tconst [orgsModalEnvType, setOrgsModalEnvType] = useState<EnvironmentType>(EnvironmentType.NonProd);\r\n\r\n\tconst orgsModalTitle =\r\n\t\torgsModalEnvType === EnvironmentType.NonProd ? \"Installing Organizations\" : \"Live Organizations\";\r\n\r\n\tconst orgNameList =\r\n\t\torgsModalEnvType === EnvironmentType.NonProd ? app.sharedInstallingOrgNames : app.sharedLiveOrgNames;\r\n\tconst totalOrgs = orgsModalEnvType === EnvironmentType.NonProd ? app.numInstallingOrgs : app.numLiveOrgs;\r\n\tconst otherOrgsMessage = getOtherOrgsMessage(totalOrgs, orgNameList.length);\r\n\r\n\tconst hasInstallingOrgNames = app.sharedInstallingOrgNames.length > 0;\r\n\tconst hasLiveOrgNames = app.sharedLiveOrgNames.length > 0;\r\n\r\n\tconst handleShowOrgsModal = useCallback(\r\n\t\t(envType: EnvironmentType) => () => {\r\n\t\t\tsetOrgsModalEnvType(envType);\r\n\t\t\tsetShowingOrgsModal(true);\r\n\t\t},\r\n\t\t[],\r\n\t);\r\n\tconst handleToggleOrgsModal = useCallback(\r\n\t\t(show: boolean) => () => {\r\n\t\t\tsetShowingOrgsModal(show);\r\n\t\t},\r\n\t\t[],\r\n\t);\r\n\r\n\tconst handleSetAppLinkRef = useCallback(\r\n\t\t(linkRef: React.RefObject<HTMLAnchorElement> | null) => setAppLinkRef(linkRef),\r\n\t\t[],\r\n\t);\r\n\r\n\tconst installingOrgsHelptext = `${app.numInstallingOrgs} organization${\r\n\t\tapp.numInstallingOrgs === 1 ? \" is\" : \"s are\"\r\n\t} installing this app.${hasInstallingOrgNames ? \" Click for a list.\" : \"\"}`;\r\n\r\n\tconst liveOrgsHelptext = `${app.numLiveOrgs} organization${\r\n\t\tapp.numLiveOrgs === 1 ? \" is\" : \"s are\"\r\n\t} live on this app.${hasLiveOrgNames ? \" Click for a list.\" : \"\"}`;\r\n\r\n\tconst viewReviewsUrl = `${marketplaceUrl}${app.appId}&tab=reviews`;\r\n\tconst reviewsHelptext = `${app.numReviews} total reviews for this app. Click to see all reviews.`;\r\n\r\n\tconst downloadPageUrl = (app.isAvailableInGallery ? marketplaceUrl : downloadUrl) + app.appId;\r\n\r\n\t//#endregion\r\n\treturn (\r\n\t\t<>\r\n\t\t\t<WidgetAppRow\r\n\t\t\t\tappId={app.appId}\r\n\t\t\t\tappName={app.appName}\r\n\t\t\t\tsubtitle={<Box title=\"The organization that created this app\">{app.appOrgName}</Box>}\r\n\t\t\t\tlinkUrl={downloadPageUrl}\r\n\t\t\t\tonLinkRefCreated={handleSetAppLinkRef}\r\n\t\t\t\tlinkTitle=\"Open this app's listing\"\r\n\t\t\t\tbelowLogoContent={\r\n\t\t\t\t\t<>\r\n\t\t\t\t\t\t{app.tesseractEnabled && (\r\n\t\t\t\t\t\t\t<Image\r\n\t\t\t\t\t\t\t\tsrc={tesseractLogo}\r\n\t\t\t\t\t\t\t\th=\"18px\"\r\n\t\t\t\t\t\t\t\tw=\"18px\"\r\n\t\t\t\t\t\t\t\ttitle=\"This app is enabled for Tesseract.\"\r\n\t\t\t\t\t\t\t\taria-label=\"This app is enabled for Tesseract\"\r\n\t\t\t\t\t\t\t\talt=\"Tesseract logo\"\r\n\t\t\t\t\t\t\t\tdisplay=\"inline-block\"\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t{app.hasDownloadableBuild && <DownloadBuildIcon />}\r\n\t\t\t\t\t</>\r\n\t\t\t\t}\r\n\t\t\t\tadditionalAppInfo={\r\n\t\t\t\t\t<VStack spacing=\"0.3em\" width=\"max-content\">\r\n\t\t\t\t\t\t<NominationInfo\r\n\t\t\t\t\t\t\tw=\"100%\"\r\n\t\t\t\t\t\t\tlatestAppVersionId={app.appId}\r\n\t\t\t\t\t\t\tnominations={app.nominations}\r\n\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t></NominationInfo>\r\n\t\t\t\t\t\t{app.notNowDecision && (\r\n\t\t\t\t\t\t\t<NotImplementingNowInfo\r\n\t\t\t\t\t\t\t\tlatestAppVersionId={app.appId}\r\n\t\t\t\t\t\t\t\tnotNowDecision={app.notNowDecision}\r\n\t\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t\t></NotImplementingNowInfo>\r\n\t\t\t\t\t\t)}\r\n\t\t\t\t\t</VStack>\r\n\t\t\t\t}\r\n\t\t\t\tbottomContent={\r\n\t\t\t\t\tapp.implementationGuideUrl && <ImplementationGuideLink url={app.implementationGuideUrl} />\r\n\t\t\t\t}\r\n\t\t\t\tactions={\r\n\t\t\t\t\tuserSecurity.canPurchase &&\r\n\t\t\t\t\tparticipantTermsId && (\r\n\t\t\t\t\t\t<NominatedAppsButtons\r\n\t\t\t\t\t\t\tapp={app}\r\n\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\tdispatch={dispatch}\r\n\t\t\t\t\t\t\tappLinkRef={appLinkRef}\r\n\t\t\t\t\t\t\tdownloadPageUrl={downloadPageUrl}\r\n\t\t\t\t\t\t\tisGalleryEnabled={isGalleryEnabled}\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t\tmiddleColumnContent={\r\n\t\t\t\t\t<Wrap spacing=\"0.25em\">\r\n\t\t\t\t\t\t{isGalleryEnabled && (\r\n\t\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t\t<WrapItem>\r\n\t\t\t\t\t\t\t\t\t<WidgetAppBadge\r\n\t\t\t\t\t\t\t\t\t\tasButton={hasInstallingOrgNames}\r\n\t\t\t\t\t\t\t\t\t\tbuttonProps={{\r\n\t\t\t\t\t\t\t\t\t\t\tonClick: hasInstallingOrgNames\r\n\t\t\t\t\t\t\t\t\t\t\t\t? handleShowOrgsModal(EnvironmentType.NonProd)\r\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined,\r\n\t\t\t\t\t\t\t\t\t\t}}\r\n\t\t\t\t\t\t\t\t\t\ttitle={installingOrgsHelptext}\r\n\t\t\t\t\t\t\t\t\t\tvalue={app.numInstallingOrgs.toString()}\r\n\t\t\t\t\t\t\t\t\t\tuseHoverTooltip\r\n\t\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t\t<Image src={installingLogo} h=\"20px\" w=\"20px\" display=\"inline\" />\r\n\t\t\t\t\t\t\t\t\t</WidgetAppBadge>\r\n\t\t\t\t\t\t\t\t</WrapItem>\r\n\t\t\t\t\t\t\t\t<WrapItem>\r\n\t\t\t\t\t\t\t\t\t<WidgetAppBadge\r\n\t\t\t\t\t\t\t\t\t\tasButton={hasLiveOrgNames}\r\n\t\t\t\t\t\t\t\t\t\tbuttonProps={{\r\n\t\t\t\t\t\t\t\t\t\t\tonClick: hasLiveOrgNames\r\n\t\t\t\t\t\t\t\t\t\t\t\t? handleShowOrgsModal(EnvironmentType.Prod)\r\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined,\r\n\t\t\t\t\t\t\t\t\t\t}}\r\n\t\t\t\t\t\t\t\t\t\ttitle={liveOrgsHelptext}\r\n\t\t\t\t\t\t\t\t\t\tvalue={app.numLiveOrgs.toString()}\r\n\t\t\t\t\t\t\t\t\t\tuseHoverTooltip\r\n\t\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t\t<Image src={liveLogo} h=\"20px\" w=\"20px\" display=\"inline\" />\r\n\t\t\t\t\t\t\t\t\t</WidgetAppBadge>\r\n\t\t\t\t\t\t\t\t</WrapItem>\r\n\t\t\t\t\t\t\t</>\r\n\t\t\t\t\t\t)}\r\n\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//disable for now\r\n\t\t\t\t\t\t\tfalse && app.numReviews > 0 && isGalleryEnabled && (\r\n\t\t\t\t\t\t\t\t<WrapItem>\r\n\t\t\t\t\t\t\t\t\t<AOLink url={viewReviewsUrl} target=\"_blank\" title={reviewsHelptext}>\r\n\t\t\t\t\t\t\t\t\t\t<WidgetAppBadge\r\n\t\t\t\t\t\t\t\t\t\t\ttitle={reviewsHelptext}\r\n\t\t\t\t\t\t\t\t\t\t\tvalue={app.numReviews.toString()}\r\n\t\t\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t\t\t<VscFeedback\r\n\t\t\t\t\t\t\t\t\t\t\t\tsize={20}\r\n\t\t\t\t\t\t\t\t\t\t\t\tcolor=\"darkblue\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{ display: \"inline\" }}\r\n\t\t\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t\t</WidgetAppBadge>\r\n\t\t\t\t\t\t\t\t\t</AOLink>\r\n\t\t\t\t\t\t\t\t</WrapItem>\r\n\t\t\t\t\t\t\t)\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t</Wrap>\r\n\t\t\t\t}\r\n\t\t\t></WidgetAppRow>\r\n\t\t\t<Modal isOpen={showingOrgsModal} onClose={handleToggleOrgsModal(false)}>\r\n\t\t\t\t<ModalOverlay />\r\n\t\t\t\t<ModalContent>\r\n\t\t\t\t\t<ModalHeader>{orgsModalTitle}</ModalHeader>\r\n\t\t\t\t\t<ModalCloseButton />\r\n\t\t\t\t\t<ModalBody pt={0}>\r\n\t\t\t\t\t\t{orgNameList.map((orgName, index) => (\r\n\t\t\t\t\t\t\t<Box key={index} fontWeight=\"bold\" ml=\"0.5em\">\r\n\t\t\t\t\t\t\t\t{orgName}\r\n\t\t\t\t\t\t\t</Box>\r\n\t\t\t\t\t\t))}\r\n\t\t\t\t\t\t{otherOrgsMessage && <Box ml=\"0.5em\">{otherOrgsMessage}</Box>}\r\n\t\t\t\t\t</ModalBody>\r\n\t\t\t\t\t<ModalFooter>\r\n\t\t\t\t\t\t<Button colorScheme=\"blue\" onClick={handleToggleOrgsModal(false)}>\r\n\t\t\t\t\t\t\tOk\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t</ModalFooter>\r\n\t\t\t\t</ModalContent>\r\n\t\t\t</Modal>\r\n\t\t</>\r\n\t);\r\n});\r\n","/**\r\n * @copyright Copyright 2021-2023 Epic Systems Corporation\r\n * @file Nominated Apps Buttons (used by the Nominated Apps widget)\r\n * @module Epic.AppOrchard.Dashboard.NominatedAppsButtons\r\n */\r\n\r\nimport { VStack } from \"@chakra-ui/react\";\r\nimport { AOLink, ContactButton } from \"ao/components/Core\";\r\nimport { WidgetActionButton } from \"ao/components/Dashboard/widgetHelpers\";\r\nimport { contactAuthor } from \"ao/data\";\r\nimport { IAppWidgetActionButtonProps } from \"ao/types/dashboard\";\r\nimport React, { FC, memo } from \"react\";\r\nimport { BiCheckCircle } from \"react-icons/bi\";\r\nimport { MarkNowImplementingNowButton } from \".\";\r\n\r\ninterface INominatedAppsButtonsProps extends IAppWidgetActionButtonProps {\r\n\tappLinkRef: React.RefObject<HTMLAnchorElement> | null;\r\n\tdownloadPageUrl: string;\r\n\tisGalleryEnabled: boolean | undefined;\r\n}\r\n\r\n/** Nominated Apps Buttons (used by the Nominated Apps widget) */\r\nexport const NominatedAppsButtons: FC<INominatedAppsButtonsProps> = memo(\r\n\t(props: INominatedAppsButtonsProps) => {\r\n\t\tconst { app, dispatch, orgId, appLinkRef, downloadPageUrl, isGalleryEnabled } = props;\r\n\r\n\t\treturn (\r\n\t\t\t<VStack w=\"100%\" spacing=\"0.25em\">\r\n\t\t\t\t<WidgetActionButton\r\n\t\t\t\t\tcolorScheme=\"green\"\r\n\t\t\t\t\tleftIcon={<BiCheckCircle size={20} />}\r\n\t\t\t\t\turl={downloadPageUrl}\r\n\t\t\t\t\ttarget=\"blank\"\r\n\t\t\t\t\ttitle=\"Open this app's listing\"\r\n\t\t\t\t\tas={AOLink}\r\n\t\t\t\t\ttextDecoration=\"none\"\r\n\t\t\t\t\t_hover={{\r\n\t\t\t\t\t\ttextDecoration: \"none\",\r\n\t\t\t\t\t\tbackground: \"green.50\",\r\n\t\t\t\t\t\tcolor: \"green\",\r\n\t\t\t\t\t}}\r\n\t\t\t\t>\r\n\t\t\t\t\tDownload\r\n\t\t\t\t</WidgetActionButton>\r\n\t\t\t\t{isGalleryEnabled && (\r\n\t\t\t\t\t<ContactButton\r\n\t\t\t\t\t\tbuttonAs={WidgetActionButton}\r\n\t\t\t\t\t\tcontactApi={contactAuthor}\r\n\t\t\t\t\t\tapiArgs={[app.appId]}\r\n\t\t\t\t\t\tbuttonCaption=\"Contact\"\r\n\t\t\t\t\t\tfinalFocusRef={appLinkRef || undefined}\r\n\t\t\t\t\t\ttitle={`Let ${app.appOrgName} know you're interested in ${app.appName}`}\r\n\t\t\t\t\t\tbuttonNotContactedHelptext=\"Send an email to the vendor indicating your interest and inviting them to start a conversation with you.\"\r\n\t\t\t\t\t\tsuccessMessage=\"An email was sent to the vendor.\"\r\n\t\t\t\t\t\terrorMessage=\"Error contacting the vendor. Please try again later or contact your Epic representative if this continues to happen.\"\r\n\t\t\t\t\t\tconfirmModalTitle={`Contact ${app.appOrgName ?? app.appName}`}\r\n\t\t\t\t\t\tconfirmModalPrompt={`This will send an email to ${\r\n\t\t\t\t\t\t\tapp.appOrgName ?? app.appName\r\n\t\t\t\t\t\t} indicating your interest and inviting them to start a conversation with you. Are you sure you want to continue?`}\r\n\t\t\t\t\t/>\r\n\t\t\t\t)}\r\n\t\t\t\t<MarkNowImplementingNowButton app={app} orgId={orgId} dispatch={dispatch} />\r\n\t\t\t</VStack>\r\n\t\t);\r\n\t},\r\n);\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file Summary of who nominated the app and when (used by the Nominated Apps widget)\r\n * @module Epic.AppOrchard.Dashboard.NominationInfo\r\n */\r\n\r\nimport { StarIcon } from \"@chakra-ui/icons\";\r\nimport { Box, TagProps } from \"@chakra-ui/react\";\r\nimport { WidgetTag } from \"ao/components/Dashboard/widgetHelpers\";\r\nimport { INomination, IUserSecurity } from \"ao/types\";\r\nimport React, { FC, memo } from \"react\";\r\n\r\ninterface IProps {\r\n\tlatestAppVersionId: number;\r\n\tnominations: INomination[];\r\n\tuserSecurity: IUserSecurity;\r\n}\r\n\r\ntype Props = IProps & TagProps;\r\n\r\n/** Summary of who nominated the app and when (used by the Nominated Apps widget) */\r\nexport const NominationInfo: FC<Props> = memo((props: Props) => {\r\n\tconst { nominations, userSecurity, latestAppVersionId, ...rest } = props;\r\n\tconst showUserName =\r\n\t\t(userSecurity.canPurchase || userSecurity.isEpicUser) && nominations.some((n) => n.userName);\r\n\r\n\tif (nominations.length === 0) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst nominationSummary = !showUserName // if current user can use name of user who nominated, don't show hover text\r\n\t\t? null\r\n\t\t: nominations.map((nom, index) => {\r\n\t\t\t\tconst isPriorVersion = latestAppVersionId !== nom.appVersionId;\r\n\t\t\t\treturn (\r\n\t\t\t\t\t<Box key={index} mt={index === 0 ? \"\" : \"0.5em\"}>\r\n\t\t\t\t\t\t{nom.userName + \" nominated\"} on {nom.instant.toLocaleDateString()}{\" \"}\r\n\t\t\t\t\t\t{isPriorVersion && (\r\n\t\t\t\t\t\t\t<Box as=\"span\" fontStyle=\"italic\" fontSize=\"0.8em\">\r\n\t\t\t\t\t\t\t\t(previous app version)\r\n\t\t\t\t\t\t\t</Box>\r\n\t\t\t\t\t\t)}\r\n\t\t\t\t\t</Box>\r\n\t\t\t\t);\r\n\t\t });\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t<WidgetTag\r\n\t\t\t\tlabel={nominations.length + \" nomination\" + (nominations.length === 1 ? \"\" : \"s\")}\r\n\t\t\t\ttooltipContent={nominationSummary}\r\n\t\t\t\ticon={StarIcon}\r\n\t\t\t\ttooltipProps={{ w: \"350px\", maxW: \"unset\" }}\r\n\t\t\t\t{...rest}\r\n\t\t\t></WidgetTag>\r\n\t\t</>\r\n\t);\r\n});\r\n","/**\r\n * @copyright Copyright 2021-2024 Epic Systems Corporation\r\n * @file Nominated apps dashboard widget\r\n * @module Epic.AppOrchard.Dashboard.Widgets.NominatedAppsWidget\r\n */\r\n\r\nimport { ISuccessHandler, useAsync } from \"@epic/react-async-hook\";\r\nimport { useDispatch } from \"@epic/react-redux-booster\";\r\nimport { config } from \"ao/appConfig\";\r\nimport { AsyncPlaceholder, ITab, SearchInput, TabbedSection } from \"ao/components/Core\";\r\nimport { getNominatedApps } from \"ao/components/Dashboard/data\";\r\nimport { useSiteInfoState } from \"ao/state/siteInfo\";\r\nimport { useNominatedAppsState } from \"ao/state/widgets/nominatedApps\";\r\nimport { updateNominatedAppsAfterLoad } from \"ao/store-methods/nominatedApps\";\r\nimport { IWidget, IWidgetProps } from \"ao/types/dashboard\";\r\nimport { getBaseUrl } from \"ao/utils/helpers\";\r\nimport React, { useCallback, useEffect, useMemo, useState } from \"react\";\r\nimport { WidgetSpinner, WidgetTable } from \"../../widgetHelpers\";\r\nimport { NominatedAppRow } from \"./helperComponents\";\r\n\r\n/** Nominated apps dashboard widget */\r\nexport const NominatedAppsWidget: IWidget = (props: IWidgetProps) => {\r\n\t//#region state and props\r\n\tconst { isExpanded, userSecurity, orgId } = props;\r\n\tconst [searchTerm, setSearchTerm] = useState<string>(\"\");\r\n\tconst handleChangeSearchTerm = useCallback((newSearchTerm: string) => setSearchTerm(newSearchTerm), []);\r\n\tconst { siteInfo } = useSiteInfoState((selectors) => selectors.getState(), []);\r\n\r\n\tconst baseUrl = useMemo(() => getBaseUrl(), []);\r\n\tconst marketplaceUrl = `${siteInfo.showroomUrl}Listing?appId=`;\r\n\tconst downloadUrl = `/Download?id=`;\r\n\tconst installingLogo = `${baseUrl}Content/images/ReviewBadge_Installing Organizations.png`;\r\n\tconst liveLogo = `${baseUrl}Content/images/ReviewBadge_Live Organizations.png`;\r\n\tconst tesseractLogo = `${baseUrl}Content/images/Tesseract_Logo.png`;\r\n\tconst entriesPerPage = config.Dashboard.WidgetAppRowsPerPage;\r\n\r\n\tconst dispatch = useDispatch();\r\n\tconst hasLoaded = useNominatedAppsState((selectors) => selectors.getHasLoaded(orgId), [orgId]);\r\n\tconst [participantTermsId] = useNominatedAppsState(\r\n\t\t(selectors) => selectors.getStaticOrgDetails(orgId),\r\n\t\t[],\r\n\t);\r\n\r\n\tconst needsReviewApps = useNominatedAppsState(\r\n\t\t(selectors) => selectors.getNeedsReviewApps({ orgId, searchTerm }),\r\n\t\t[orgId, searchTerm],\r\n\t);\r\n\tconst notNowApps = useNominatedAppsState(\r\n\t\t(selectors) => selectors.getNotImplementingNowApps({ orgId, searchTerm }),\r\n\t\t[orgId, searchTerm],\r\n\t);\r\n\r\n\tconst handleNominatedAppsLoaded = useCallback<ISuccessHandler<typeof getNominatedApps>>(\r\n\t\t(response, extras) => {\r\n\t\t\tconst [orgId] = extras.params;\r\n\t\t\tupdateNominatedAppsAfterLoad(\r\n\t\t\t\tdispatch,\r\n\t\t\t\torgId,\r\n\t\t\t\tresponse.nominatedApps,\r\n\t\t\t\tresponse.participantTermsId,\r\n\t\t\t\tresponse.apiLicenseAgreementId,\r\n\t\t\t\tresponse.hasSignedAnyApiLicenseAgreement,\r\n\t\t\t\tresponse.hasSignedCurrentApiLicenseAgreement,\r\n\t\t\t);\r\n\t\t},\r\n\t\t[dispatch],\r\n\t);\r\n\tconst [LoadingPlaceholder, loadNominatedApps] = useAsync(getNominatedApps, AsyncPlaceholder, {\r\n\t\texecuteImmediately: false,\r\n\t\tdisplayName: \"getNominatedApps\",\r\n\t\t// `extras` will contain `params` field which has the params passed to getNominatedApps (namely the org ID)\r\n\t\t// this is needed rather than using the orgId from props directly in handleNominatedAppsLoaded because\r\n\t\t// that will result in a stale closure (https://gitlab.epic.com/foundations/react-async-hook/-/issues/2)\r\n\t\tonSuccess: (response, extras) => handleNominatedAppsLoaded(response, extras),\r\n\t});\r\n\r\n\tuseEffect(() => {\r\n\t\t// if/when this issue (https://gitlab.epic.com/foundations/react-async-hook/-/issues/3) is fixed\r\n\t\t// we can use !hasLoaded as a executeImmediately param for useAsync instead to be a bit cleaner\r\n\t\tif (!hasLoaded) {\r\n\t\t\tloadNominatedApps(orgId);\r\n\t\t}\r\n\t}, [hasLoaded, loadNominatedApps, orgId]);\r\n\r\n\t//#endregion\r\n\r\n\tconst tabs: ITab[] = [\r\n\t\t{\r\n\t\t\ttabName: \"Needs Review\",\r\n\t\t\tcountPrefix: needsReviewApps.length,\r\n\t\t\thelptext: \"Nominated apps that need review\",\r\n\t\t\tcontent: (\r\n\t\t\t\t<WidgetTable\r\n\t\t\t\t\tnoRecordsMessage=\"No matching apps\"\r\n\t\t\t\t\tentriesPerPage={!isExpanded ? entriesPerPage : undefined}\r\n\t\t\t\t\tisExpanded={isExpanded}\r\n\t\t\t\t>\r\n\t\t\t\t\t{needsReviewApps.map((a) => (\r\n\t\t\t\t\t\t<NominatedAppRow\r\n\t\t\t\t\t\t\tkey={a.appId}\r\n\t\t\t\t\t\t\tapp={a}\r\n\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t\tmarketplaceUrl={marketplaceUrl}\r\n\t\t\t\t\t\t\tdownloadUrl={downloadUrl}\r\n\t\t\t\t\t\t\ttesseractLogo={tesseractLogo}\r\n\t\t\t\t\t\t\tparticipantTermsId={participantTermsId}\r\n\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\tdispatch={dispatch}\r\n\t\t\t\t\t\t\tinstallingLogo={installingLogo}\r\n\t\t\t\t\t\t\tliveLogo={liveLogo}\r\n\t\t\t\t\t\t\tisGalleryEnabled={siteInfo.isGalleryEnabled}\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</WidgetTable>\r\n\t\t\t),\r\n\t\t},\r\n\t\t{\r\n\t\t\ttabName: \"Not Now\",\r\n\t\t\tcountPrefix: notNowApps.length,\r\n\t\t\thelptext: \"Nominated apps that have been marked as not implementing now\",\r\n\t\t\tcontent: (\r\n\t\t\t\t<WidgetTable\r\n\t\t\t\t\tnoRecordsMessage=\"No matching apps\"\r\n\t\t\t\t\tentriesPerPage={!isExpanded ? entriesPerPage : undefined}\r\n\t\t\t\t\tisExpanded={isExpanded}\r\n\t\t\t\t>\r\n\t\t\t\t\t{notNowApps.map((a) => (\r\n\t\t\t\t\t\t<NominatedAppRow\r\n\t\t\t\t\t\t\tkey={a.appId}\r\n\t\t\t\t\t\t\tapp={a}\r\n\t\t\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t\t\t\tmarketplaceUrl={marketplaceUrl}\r\n\t\t\t\t\t\t\tdownloadUrl={downloadUrl}\r\n\t\t\t\t\t\t\ttesseractLogo={tesseractLogo}\r\n\t\t\t\t\t\t\tparticipantTermsId={participantTermsId}\r\n\t\t\t\t\t\t\torgId={orgId}\r\n\t\t\t\t\t\t\tdispatch={dispatch}\r\n\t\t\t\t\t\t\tinstallingLogo={installingLogo}\r\n\t\t\t\t\t\t\tliveLogo={liveLogo}\r\n\t\t\t\t\t\t\tisGalleryEnabled={siteInfo.isGalleryEnabled}\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</WidgetTable>\r\n\t\t\t),\r\n\t\t},\r\n\t];\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t{isExpanded && ( //show search bar if in expanded/popup mode\r\n\t\t\t\t<SearchInput\r\n\t\t\t\t\tplaceholder=\"Search for apps by app name, company name, client ID\"\r\n\t\t\t\t\tonChangeCallback={handleChangeSearchTerm}\r\n\t\t\t\t\tinputGroupProps={{ mb: \"1rem\" }}\r\n\t\t\t\t\ttab-name\r\n\t\t\t\t></SearchInput>\r\n\t\t\t)}\r\n\t\t\t<LoadingPlaceholder\r\n\t\t\t\tinProgressIndicator={<WidgetSpinner />}\r\n\t\t\t\terrorMessage=\"Error loading apps from the server\"\r\n\t\t\t\tuseLastRequestForErrors\r\n\t\t\t>\r\n\t\t\t\t<TabbedSection tabs={tabs} />\r\n\t\t\t</LoadingPlaceholder>\r\n\t\t</>\r\n\t);\r\n};\r\n\r\nNominatedAppsWidget.descriptor = \"nominatedApps\";\r\n","/**\r\n * @copyright Copyright 2021-2025 Epic Systems Corporation\r\n * @file dashboard data and APIs\r\n * @module Epic.AppOrchard.Dashboard.Data\r\n */\r\n\r\nimport { INotImplementingNowDecision } from \"ao/types\";\r\nimport {\r\n\tIAvailableDashboards,\r\n\tIGetAttestationResponseModel,\r\n\tIHomegrownAppsForOrgResponseModel,\r\n\tIInProgressAppsForOrgResponseModel,\r\n\tILiveAppsForOrgResponseModel,\r\n\tINominatedAppsForOrgResponseModel,\r\n\tISaveDefaultDashboardResponse,\r\n\tISaveWidgetPrefsResponse,\r\n\tIWidget,\r\n\tIWidgetPreferences,\r\n} from \"ao/types/dashboard\";\r\nimport { IUpdateCustomerAppLicenseRequest } from \"../../../data\";\r\nimport api from \"../../../utils/api\";\r\nimport { HomegrownAppsWidget, InProgressAppsWidget, LiveAppsWidget, NominatedAppsWidget } from \"../widgets\";\r\n\r\n/**\r\n * Load all dashboards available to a user (live + user has security to access) from the server\r\n */\r\nexport async function getAvailableDashboards(): Promise<IAvailableDashboards> {\r\n\tconst data: IAvailableDashboards = await api.get<IAvailableDashboards>(\"/api/Dashboard/LoadAvailable\");\r\n\treturn data;\r\n}\r\n\r\n/**\r\n * Save user's dashboard preferences (widgets to show, ordering) to the server\r\n * @param dashboardDescriptor descriptor to identify dashboard prefs are being saved for\r\n * @param prefs widget prefs to save\r\n * @returns\r\n */\r\nexport async function saveDashboardPreferences(\r\n\tdashboardDescriptor: string,\r\n\tprefs: IWidgetPreferences[],\r\n): Promise<ISaveWidgetPrefsResponse> {\r\n\tconst response: ISaveWidgetPrefsResponse = await api.post<ISaveWidgetPrefsResponse>(\r\n\t\t\"/api/Dashboard/UpdatePreferences\",\r\n\t\t{ Descriptor: dashboardDescriptor, WidgetPreferences: prefs },\r\n\t);\r\n\treturn response;\r\n}\r\n\r\n/**\r\n * Set the dashboard as the user's default dashboard for display\r\n * @param dashboardDescriptor descriptor to identify the dashboard to the server\r\n * @returns\r\n */\r\nexport async function setDashboardAsDefault(\r\n\tdashboardDescriptor: string,\r\n): Promise<ISaveDefaultDashboardResponse> {\r\n\tconst response: ISaveDefaultDashboardResponse = await api.post<ISaveDefaultDashboardResponse>(\r\n\t\t\"/api/Dashboard/SetAsDefault\",\r\n\t\t{ Descriptor: dashboardDescriptor },\r\n\t);\r\n\treturn response;\r\n}\r\n\r\n/**\r\n * Get nominated apps for given customer,\r\n * including info about apps that are nominated but marked as not implementing now\r\n * @param orgId customer organization identifier\r\n * @returns\r\n */\r\nexport async function getNominatedApps(orgId: number): Promise<INominatedAppsForOrgResponseModel> {\r\n\tconst response: INominatedAppsForOrgResponseModel = await api.get<INominatedAppsForOrgResponseModel>(\r\n\t\t`/api/NominatedApps/LoadAllForOrg?orgId=${orgId}`,\r\n\t);\r\n\treturn response;\r\n}\r\n\r\n/**\r\n * Marks an app as not implementing now for a given org, or updates the not implementing now details.\r\n * @param appId client app ID\r\n * @param _orgID customer org ID, not used in API call directly, but passed here so it can be available to the success handler\r\n * @param privateReason reason only visible to AOPPs\r\n * @param publicReason reason visible to all users from the customer org\r\n * @param notifyInterestedUsers whether to notify interested/nominating users of this decision\r\n * @returns\r\n */\r\nexport async function markAsNotImplementingNow(\r\n\tappId: number,\r\n\t_orgId: number,\r\n\tprivateReason: string,\r\n\tpublicReason: string,\r\n\tnotifyInterestedUsers: boolean,\r\n\tdeleted: boolean,\r\n): Promise<INotImplementingNowDecision | null> {\r\n\tconst response = await api.post<INotImplementingNowDecision | null>(\r\n\t\t\"/api/NominatedApps/MarkAsNotImplementingNow\",\r\n\t\t{\r\n\t\t\tAppId: appId,\r\n\t\t\tPrivateReason: privateReason,\r\n\t\t\tPublicReason: publicReason,\r\n\t\t\tNotifyInterestedUsers: notifyInterestedUsers,\r\n\t\t\tDeleted: deleted,\r\n\t\t},\r\n\t);\r\n\treturn response;\r\n}\r\n\r\n/**\r\n * Get in progress apps for given customer\r\n * @param orgId customer organization identifier\r\n * @returns\r\n */\r\nexport async function getInProgressApps(orgId: number): Promise<IInProgressAppsForOrgResponseModel> {\r\n\tconst response: IInProgressAppsForOrgResponseModel = await api.get<IInProgressAppsForOrgResponseModel>(\r\n\t\t`/api/InProgressApps/LoadAllForOrg?orgId=${orgId}`,\r\n\t);\r\n\treturn response;\r\n}\r\n\r\n/**\r\n * Get live apps for given customer\r\n * @param orgId customer organization identifier\r\n * @returns\r\n */\r\nexport async function getLiveApps(orgId: number): Promise<ILiveAppsForOrgResponseModel> {\r\n\tconst response: ILiveAppsForOrgResponseModel = await api.get<ILiveAppsForOrgResponseModel>(\r\n\t\t`/api/LiveApps/LoadAllForOrg?orgId=${orgId}`,\r\n\t);\r\n\treturn response;\r\n}\r\n\r\n/**\r\n * Get homegrown (customer created) apps for the customer\r\n * @param orgId customer organization identifier\r\n * @returns\r\n */\r\nexport async function getHomegrownApps(orgId: number): Promise<IHomegrownAppsForOrgResponseModel> {\r\n\tconst response: IHomegrownAppsForOrgResponseModel = await api.get<IHomegrownAppsForOrgResponseModel>(\r\n\t\t`/api/HomegrownApps/LoadAllForOrg?orgId=${orgId}`,\r\n\t);\r\n\treturn response;\r\n}\r\n\r\n/**\r\n * Create license-level info for a customer app, or update an existing license\r\n * @param data data to create or update\r\n * @returns created/updated license on success, throws error on failure\r\n */\r\nexport async function updateCustomerAppLicenseState(\r\n\tdata: IUpdateCustomerAppLicenseRequest,\r\n): Promise<IHomegrownAppsForOrgResponseModel> {\r\n\tconst result: IHomegrownAppsForOrgResponseModel = await api.post<IHomegrownAppsForOrgResponseModel>(\r\n\t\t\"/api/HomegrownApps/UpdateCustomerAppLicenseState\",\r\n\t\tdata,\r\n\t);\r\n\r\n\treturn result;\r\n}\r\n\r\n/**\r\n * Get attestation data for the app\r\n * @param appId client application identifier\r\n * @returns\r\n */\r\nexport async function getAttestation(appId: number): Promise<IGetAttestationResponseModel> {\r\n\tconst response: IGetAttestationResponseModel = await api.get<IGetAttestationResponseModel>(\r\n\t\t`/api/HomegrownApps/LoadAttestation?appId=${appId}`,\r\n\t);\r\n\treturn response;\r\n}\r\n\r\n/**\r\n * Get all widgets known on the client as a map from the descriptor to the widget component.\r\n * When new widgets are created they should be added here and to the data.test.ts unit test file.\r\n */\r\nexport function getDefinedWidgets(): Map<string, IWidget> {\r\n\tconst definedWidgets: Map<string, IWidget> = new Map([\r\n\t\t// [descriptor, component]\r\n\t\t[NominatedAppsWidget.descriptor, NominatedAppsWidget],\r\n\t\t[InProgressAppsWidget.descriptor, InProgressAppsWidget],\r\n\t\t[LiveAppsWidget.descriptor, LiveAppsWidget],\r\n\t\t[HomegrownAppsWidget.descriptor, HomegrownAppsWidget],\r\n\t]);\r\n\treturn definedWidgets;\r\n}\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file Action button on a dashboard widget\r\n * @module Epic.AppOrchard.Dashboard.WidgetActionButton\r\n */\r\n\r\nimport { Button, ButtonProps, Center, ComponentWithAs, Flex, GridItem, SimpleGrid } from \"@chakra-ui/react\";\r\nimport React from \"react\";\r\n\r\n/** Action button on a dashboard widget. Used to keep consistent formatting across buttons */\r\nexport const WidgetActionButton: ComponentWithAs<\"button\", ButtonProps> = (props: ButtonProps) => {\r\n\tconst { leftIcon, children, ...rest } = props;\r\n\r\n\treturn (\r\n\t\t<Button\r\n\t\t\t{...rest}\r\n\t\t\tvariant=\"outline\"\r\n\t\t\tsize=\"sm\"\r\n\t\t\tw=\"100%\"\r\n\t\t\twhiteSpace=\"normal\"\r\n\t\t\th=\"unset\"\r\n\t\t\tminH=\"8\"\r\n\t\t\tdisplay=\"block\"\r\n\t\t\tpt=\"0.2em\"\r\n\t\t\tpb=\"0.2em\"\r\n\t\t>\r\n\t\t\t<SimpleGrid columns={12}>\r\n\t\t\t\t<GridItem colSpan={{ base: 1, lg: 2 }}>\r\n\t\t\t\t\t<Flex justify=\"flex-start\">{leftIcon}</Flex>\r\n\t\t\t\t</GridItem>\r\n\t\t\t\t<GridItem colSpan={{ base: 11, lg: 10 }} ml={{ base: \"0.5em\", lg: \"0.25em\" }}>\r\n\t\t\t\t\t<Flex justify=\"flex-start\" h=\"100%\">\r\n\t\t\t\t\t\t<Center>{children}</Center>\r\n\t\t\t\t\t</Flex>\r\n\t\t\t\t</GridItem>\r\n\t\t\t</SimpleGrid>\r\n\t\t</Button>\r\n\t);\r\n};\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file A badge for an app highlighting a feature\r\n * \t\tCurrently used by widgets but could potentially be used elsewhere\r\n * @module Epic.AppOrchard.Dashboard.WidgetAppBadge\r\n */\r\n\r\nimport { Box, ButtonProps, Center } from \"@chakra-ui/react\";\r\nimport { AOTooltip } from \"ao/components/Core\";\r\nimport React, { FC, memo } from \"react\";\r\n\r\ninterface IProps {\r\n\ttitle: string;\r\n\tvalue?: string;\r\n\tchildren: React.ReactNode;\r\n\tuseHoverTooltip?: boolean;\r\n\tasButton?: boolean;\r\n\tbuttonProps?: ButtonProps;\r\n}\r\n\r\n/** A badge for an app highlighting a feature\r\n * \t\tCurrently used by widgets but could potentially be used elsewhere */\r\nexport const WidgetAppBadge: FC<IProps> = memo((props: IProps) => {\r\n\tconst { title, value, useHoverTooltip, children, asButton, buttonProps } = props;\r\n\tconst height = \"40px\";\r\n\tconst minWidth = \"40px\";\r\n\tconst content = (\r\n\t\t<Center\r\n\t\t\th={height}\r\n\t\t\tminW={minWidth}\r\n\t\t\tdisplay=\"inline-block\"\r\n\t\t\tbg=\"#eeebeb\"\r\n\t\t\tp=\"5px\"\r\n\t\t\tcolor=\"#6d6767\"\r\n\t\t\tborderRadius=\"2px\"\r\n\t\t\ttitle={!useHoverTooltip ? title : \"\"}\r\n\t\t>\r\n\t\t\t{value && (\r\n\t\t\t\t<Box fontSize=\"1.1em\" fontWeight=\"bold\" as=\"span\">\r\n\t\t\t\t\t{value}\r\n\t\t\t\t</Box>\r\n\t\t\t)}\r\n\t\t\t{children}\r\n\t\t</Center>\r\n\t);\r\n\treturn useHoverTooltip ? (\r\n\t\t<AOTooltip\r\n\t\t\thelptext={title}\r\n\t\t\tasButton={asButton}\r\n\t\t\tbuttonProps={{ ...buttonProps, h: height, minW: minWidth }}\r\n\t\t>\r\n\t\t\t{content}\r\n\t\t</AOTooltip>\r\n\t) : (\r\n\t\t<>{content}</>\r\n\t);\r\n});\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file One application row in a dashboard widget table\r\n * @module Epic.AppOrchard.Dashboard.WidgetAppRow\r\n */\r\n\r\nimport {\r\n\tAspectRatio,\r\n\tBox,\r\n\tCenter,\r\n\tDivider,\r\n\tFlex,\r\n\tGridItem,\r\n\tHStack,\r\n\tImage,\r\n\tListItem,\r\n\tSimpleGrid,\r\n\tuseBreakpointValue,\r\n} from \"@chakra-ui/react\";\r\nimport { config } from \"ao/appConfig\";\r\nimport { AOLink } from \"ao/components/Core\";\r\nimport { getBaseUrl } from \"ao/utils/helpers\";\r\nimport { childrenWithoutFragment } from \"ao/utils/reactHelpers\";\r\nimport React, { FC, memo, useEffect, useMemo, useRef } from \"react\";\r\n\r\nexport interface IWidgetAppRowProps {\r\n\tappId: number;\r\n\t/** actions, e.g. buttons or inputs */\r\n\tactions?: React.ReactNode;\r\n\t/** Content that shows underneath the app row */\r\n\tbottomContent?: React.ReactNode;\r\n\t/** content to show in the middle column of the app row,\r\n\t * in between the standard app info (name, logo, etc) and content on the right */\r\n\tmiddleColumnContent?: React.ReactNode;\r\n\t/** additional info about the app shown under app name or to the side if no actions passed */\r\n\tadditionalAppInfo?: React.ReactNode;\r\n\tappName: string;\r\n\t/** page to link to when app is clicked */\r\n\tlinkUrl?: string;\r\n\tlinkTitle?: string;\r\n\t/** show under app name */\r\n\tsubtitle?: React.ReactNode;\r\n\tbelowLogoContent?: React.ReactNode;\r\n\t/** get a reference to the app name link, can be used to focus something in the app after an action is taken */\r\n\tonLinkRefCreated?: (linkRef: React.RefObject<HTMLAnchorElement> | null) => void;\r\n}\r\n\r\n/** One application row in a dashboard widget table.\r\n * Some of the content is shown in different places depending on the screen size and which content is passed to try to prevent empty sections in the app row */\r\nexport const WidgetAppRow: FC<IWidgetAppRowProps> = memo((props: IWidgetAppRowProps) => {\r\n\tconst {\r\n\t\tappId,\r\n\t\tappName,\r\n\t\tsubtitle,\r\n\t\tactions,\r\n\t\tlinkUrl,\r\n\t\tbottomContent,\r\n\t\tlinkTitle,\r\n\t\tadditionalAppInfo,\r\n\t\tmiddleColumnContent,\r\n\t\tbelowLogoContent,\r\n\t\tonLinkRefCreated,\r\n\t} = props;\r\n\tconst baseUrl = useMemo(() => getBaseUrl(), []);\r\n\tconst thumbnailUrl = `${baseUrl}Gallery/Thumbnail?appId=${appId}`;\r\n\tconst fallbackThumbnailUrl = `${baseUrl}Content/images/app_placeholder.png`;\r\n\tconst thumbnailColor = \"appThumbnailBackground.\" + (appId % config.NumAppThumbnailColors);\r\n\tconst isMobile = useBreakpointValue({ base: true, lg: false });\r\n\tconst linkRef = useRef<HTMLAnchorElement>(null);\r\n\r\n\tuseEffect(() => onLinkRefCreated && onLinkRefCreated(linkRef), [onLinkRefCreated]);\r\n\r\n\treturn (\r\n\t\t<ListItem>\r\n\t\t\t<SimpleGrid\r\n\t\t\t\tcolumns={12}\r\n\t\t\t\tp=\"0.5em\"\r\n\t\t\t\tborderRadius=\"4px\"\r\n\t\t\t\tbackgroundColor=\"white\"\r\n\t\t\t\tm=\"6px 0\"\r\n\t\t\t\tborder=\"1px solid lightgrey\"\r\n\t\t\t>\r\n\t\t\t\t<GridItem colSpan={{ base: 3, lg: 1 }}>\r\n\t\t\t\t\t{/* App logo */}\r\n\t\t\t\t\t<Center>\r\n\t\t\t\t\t\t<AspectRatio maxW=\"55px\" ratio={1} flex=\"1 1 auto\">\r\n\t\t\t\t\t\t\t<Image\r\n\t\t\t\t\t\t\t\tsrc={thumbnailUrl}\r\n\t\t\t\t\t\t\t\tfallbackSrc={fallbackThumbnailUrl}\r\n\t\t\t\t\t\t\t\talt=\"App logo\"\r\n\t\t\t\t\t\t\t\tbackground={thumbnailColor}\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t</AspectRatio>\r\n\t\t\t\t\t</Center>\r\n\t\t\t\t\t{childrenWithoutFragment(belowLogoContent) && (\r\n\t\t\t\t\t\t<Center>\r\n\t\t\t\t\t\t\t<HStack spacing=\"0.5em\" mt=\"0.25em\">\r\n\t\t\t\t\t\t\t\t{belowLogoContent}\r\n\t\t\t\t\t\t\t</HStack>\r\n\t\t\t\t\t\t</Center>\r\n\t\t\t\t\t)}\r\n\t\t\t\t</GridItem>\r\n\t\t\t\t<GridItem colSpan={{ base: 9, lg: 4 }} ml=\"0.75em\" mr=\"0.5em\">\r\n\t\t\t\t\t{/* App name, org name, and potentially actions or other app info depending on screen size and what's passed */}\r\n\r\n\t\t\t\t\t{linkUrl ? (\r\n\t\t\t\t\t\t<AOLink\r\n\t\t\t\t\t\t\tref={linkRef}\r\n\t\t\t\t\t\t\tvariant=\"black\"\r\n\t\t\t\t\t\t\turl={linkUrl}\r\n\t\t\t\t\t\t\ttitle={linkTitle}\r\n\t\t\t\t\t\t\ttarget=\"_blank\"\r\n\t\t\t\t\t\t\tfontWeight=\"bold\"\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t{appName}\r\n\t\t\t\t\t\t</AOLink>\r\n\t\t\t\t\t) : (\r\n\t\t\t\t\t\t<Box fontWeight=\"bold\">{appName}</Box>\r\n\t\t\t\t\t)}\r\n\t\t\t\t\t{subtitle && <Box>{subtitle}</Box>}\r\n\t\t\t\t\t{actions || isMobile ? (\r\n\t\t\t\t\t\t<Box mt=\"0.6em\" textAlign=\"left\">\r\n\t\t\t\t\t\t\t{additionalAppInfo}\r\n\t\t\t\t\t\t</Box>\r\n\t\t\t\t\t) : null}\r\n\t\t\t\t</GridItem>\r\n\t\t\t\t<GridItem\r\n\t\t\t\t\tcolSpan={{ base: 12, lg: 3 }}\r\n\t\t\t\t\tml={{ base: 0, lg: \"0.75em\" }}\r\n\t\t\t\t\tmt={{ base: \"0.5em\", lg: 0 }}\r\n\t\t\t\t>\r\n\t\t\t\t\t<Flex justify=\"flex-start\"> {middleColumnContent}</Flex>\r\n\t\t\t\t</GridItem>\r\n\t\t\t\t<GridItem colSpan={{ base: 12, lg: 4 }} mt={{ base: \"0.5em\", lg: 0 }}>\r\n\t\t\t\t\t{/* Actions or other app info depending on screen size and what's passed */}\r\n\t\t\t\t\t{actions ? (\r\n\t\t\t\t\t\t<Flex justify={{ base: \"flex-start\", lg: \"flex-end\" }} mr=\"0.5em\">\r\n\t\t\t\t\t\t\t{actions}\r\n\t\t\t\t\t\t</Flex>\r\n\t\t\t\t\t) : !isMobile ? (\r\n\t\t\t\t\t\t<Flex justify=\"flex-end\" mr=\"0.5em\" textAlign=\"right\">\r\n\t\t\t\t\t\t\t{additionalAppInfo}\r\n\t\t\t\t\t\t</Flex>\r\n\t\t\t\t\t) : null}\r\n\t\t\t\t</GridItem>\r\n\t\t\t\t{childrenWithoutFragment(bottomContent) && (\r\n\t\t\t\t\t<GridItem colSpan={12} mt={{ base: \"0.5em\", lg: 0 }}>\r\n\t\t\t\t\t\t<Divider m=\"0.5em 0\" />\r\n\t\t\t\t\t\t<HStack spacing=\"1em\">{bottomContent}</HStack>\r\n\t\t\t\t\t</GridItem>\r\n\t\t\t\t)}\r\n\t\t\t</SimpleGrid>\r\n\t\t</ListItem>\r\n\t);\r\n});\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file Spinner component for widgets to use for consistent loading indicator\r\n * @module Epic.AppOrchard.Dashboard.WidgetSpinner\r\n */\r\nimport { Spinner, VisuallyHidden } from \"@chakra-ui/react\";\r\nimport React, { FC } from \"react\";\r\n\r\n/** Spinner component for widgets to use for consistent loading indicator */\r\nexport const WidgetSpinner: FC = () => {\r\n\treturn (\r\n\t\t<Spinner role=\"status\" borderWidth=\"5px\" display=\"block\" m=\"5rem auto 3rem auto\" w=\"5rem\" h=\"5rem\">\r\n\t\t\t<VisuallyHidden>Loading</VisuallyHidden>\r\n\t\t</Spinner>\r\n\t);\r\n};\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file Component for showing a table inside a dashboard widget\r\n * @module Epic.AppOrchard.Dashboard.WidgetTable\r\n */\r\n\r\nimport { Box, Center, List } from \"@chakra-ui/layout\";\r\nimport { useBreakpointValue } from \"@chakra-ui/react\";\r\nimport { PaginatedList } from \"ao/components/Core\";\r\nimport React, { FC, memo } from \"react\";\r\n\r\nexport interface IWidgetTableProps {\r\n\tnoRecordsMessage: string;\r\n\tchildren: React.ReactNode;\r\n\t/** If defined, output will be paginated with this many items per page. If undefined show all entries with scrollbar */\r\n\tentriesPerPage?: number;\r\n\tisExpanded: boolean;\r\n}\r\n\r\n/** Component for showing a table inside a dashboard widget */\r\nexport const WidgetTable: FC<IWidgetTableProps> = memo((props: IWidgetTableProps) => {\r\n\tconst { noRecordsMessage, children, entriesPerPage, isExpanded } = props;\r\n\tconst entriesToShowPerPage = entriesPerPage || 2;\r\n\tconst expandedHeight = useBreakpointValue({ base: \"50vh\", xl: \"60vh\", \"2xl\": \"65vh\", \"3xl\": \"70vh\" });\r\n\r\n\tif (React.Children.count(children) === 0) {\r\n\t\treturn (\r\n\t\t\t<Center\r\n\t\t\t\tfontStyle=\"italic\"\r\n\t\t\t\th={isExpanded ? \"50vh\" : \"unset\"}\r\n\t\t\t\tfontSize={isExpanded ? \"1.75em\" : \"1.25em\"}\r\n\t\t\t>\r\n\t\t\t\t{noRecordsMessage}\r\n\t\t\t</Center>\r\n\t\t);\r\n\t}\r\n\r\n\treturn (\r\n\t\t<List>\r\n\t\t\t{entriesPerPage ? (\r\n\t\t\t\t<PaginatedList entriesPerPage={entriesToShowPerPage} h=\"2.25em\">\r\n\t\t\t\t\t{children}\r\n\t\t\t\t</PaginatedList>\r\n\t\t\t) : (\r\n\t\t\t\t<Box h={isExpanded ? expandedHeight : \"unset\"} overflowX=\"hidden\">\r\n\t\t\t\t\t{children}\r\n\t\t\t\t</Box>\r\n\t\t\t)}\r\n\t\t</List>\r\n\t);\r\n});\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file A tag that highlights details about an object shown in a widget\r\n * @module Epic.AppOrchard.Dashboard.WidgetTag\r\n */\r\n\r\nimport { IconProps, MergeWithAs, Tag, TagLabel, TagLeftIcon, TagProps, TagRightIcon } from \"@chakra-ui/react\";\r\nimport { AOTooltip } from \"ao/components/Core\";\r\nimport { ITooltipWithoutChildrenProps } from \"ao/components/Core/AOTooltip\";\r\nimport React, { FC, memo } from \"react\";\r\ntype IconPropsType = MergeWithAs<React.ComponentProps<\"svg\">, React.ComponentProps<\"svg\">, IconProps, \"svg\">;\r\n\r\ninterface IProps {\r\n\t/** text label shown in the tag */\r\n\tlabel: React.ReactNode;\r\n\t/** if passed, the tag will be a trigger for a tooltip with this content */\r\n\ttooltipContent?: React.ReactNode;\r\n\ttooltipProps?: ITooltipWithoutChildrenProps;\r\n\t/** icon to show to the left of the tag label */\r\n\ticon?: any;\r\n\t/** icon to show to the right of the tag label */\r\n\trightIcon?: any;\r\n\t/** props for the icon */\r\n\ticonProps?: IconPropsType;\r\n\t/** props for the right icon */\r\n\trightIconProps?: IconPropsType;\r\n}\r\n\r\ntype Props = IProps & TagProps;\r\n\r\n/** A tag that highlights details about an object shown in a widget and optionally shows helptext on hover/click, etc */\r\nexport const WidgetTag: FC<Props> = memo((props: Props) => {\r\n\tconst {\r\n\t\ttooltipContent,\r\n\t\tlabel,\r\n\t\ticon,\r\n\t\ticonProps,\r\n\t\ttooltipProps,\r\n\t\trightIcon,\r\n\t\trightIconProps,\r\n\t\t...rest\r\n\t} = props;\r\n\tconst tag = (\r\n\t\t<Tag {...rest} color=\"aoGreen.foreground\" background=\"aoGreen.background\">\r\n\t\t\t{icon && <TagLeftIcon as={icon} {...iconProps} />}\r\n\t\t\t<TagLabel>{label}</TagLabel>\r\n\t\t\t{rightIcon && <TagRightIcon as={rightIcon} {...rightIconProps} />}\r\n\t\t</Tag>\r\n\t);\r\n\treturn tooltipContent ? (\r\n\t\t<AOTooltip\r\n\t\t\thelptext={tooltipContent}\r\n\t\t\t{...tooltipProps}\r\n\t\t\tboxProps={{ display: \"inline\", width: \"100%\" }}\r\n\t\t>\r\n\t\t\t{tag}\r\n\t\t</AOTooltip>\r\n\t) : (\r\n\t\ttag\r\n\t);\r\n});\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file Button to mark app as not implementing now (used by the Nominated Apps widget)\r\n * @module Epic.AppOrchard.Dashboard.MarkNowImplementingNowButton\r\n */\r\nimport { WarningTwoIcon } from \"@chakra-ui/icons\";\r\nimport {\r\n\tAs,\r\n\tBox,\r\n\tButton,\r\n\tButtonProps,\r\n\tCheckbox,\r\n\tFlex,\r\n\tFormControl,\r\n\tFormLabel,\r\n\tModal,\r\n\tModalBody,\r\n\tModalCloseButton,\r\n\tModalContent,\r\n\tModalFooter,\r\n\tModalHeader,\r\n\tModalOverlay,\r\n\tSpacer,\r\n\tText,\r\n\tuseDisclosure,\r\n\tVStack,\r\n} from \"@chakra-ui/react\";\r\nimport { ISuccessHandler, useAsync } from \"@epic/react-async-hook\";\r\nimport { IDispatch } from \"@epic/react-redux-booster\";\r\nimport { AOTooltip, ConfirmationModal, StatusAlert, TextareaWithRemainingChars } from \"ao/components/Core\";\r\nimport { markAsNotImplementingNow } from \"ao/components/Dashboard/data\";\r\nimport { WidgetActionButton } from \"ao/components/Dashboard/widgetHelpers\";\r\nimport { updateNotImplementingNowDetails } from \"ao/store-methods/nominatedApps\";\r\nimport { INominatedApp } from \"ao/types\";\r\nimport { isInFlight, lastExecutionErrored } from \"ao/utils/useAsyncHelpers\";\r\nimport React, { ChangeEvent, FC, memo, useCallback, useState } from \"react\";\r\nimport { AiOutlineClockCircle } from \"react-icons/ai\";\r\nimport { BsFillQuestionCircleFill } from \"react-icons/bs\";\r\n\r\ntype Props = ButtonProps & IProps;\r\n\r\ninterface IProps {\r\n\t/** If provided, use onsuccess instead of dispatch */\r\n\tapp: Partial<INominatedApp>;\r\n\torgId?: number;\r\n\tdispatch?: IDispatch;\r\n\tsuccessHandler?: (...args: any[]) => void;\r\n\t/** If provided, use instead of default alert */\r\n\tfailureHandler?: (...args: any[]) => void;\r\n\t/** button-like component to render the button as */\r\n\tbuttonAs?: As;\r\n\tinterestedCount?: number;\r\n\tbuttonText?: string;\r\n\texcludeIcon?: boolean;\r\n\ticonColor?: string;\r\n}\r\n\r\n/** Button to mark app as not implementing now (used by the Nominated Apps widget) */\r\nexport const MarkNowImplementingNowButton: FC<Props> = memo((props: Props) => {\r\n\tconst {\r\n\t\tapp,\r\n\t\tdispatch,\r\n\t\torgId,\r\n\t\tsuccessHandler,\r\n\t\tfailureHandler,\r\n\t\tinterestedCount,\r\n\t\tbuttonAs,\r\n\t\tbuttonText,\r\n\t\texcludeIcon,\r\n\t\ticonColor,\r\n\t\t...rest\r\n\t} = props;\r\n\r\n\t//#region state and handlers\r\n\tconst hasSavedNotNowDetails = app?.notNowDecision != null;\r\n\tconst hasNominations =\r\n\t\t(interestedCount && interestedCount > 0) || (app?.nominations != null && app?.nominations.length > 0);\r\n\tconst deleteNotNowHelptext = `Remove the 'not implementing now' status for this product, which will allow the product to be nominated again by users from your organization${\r\n\t\thasNominations ? \" and move it back into the Needs Review tab\" : \"\"\r\n\t}.`;\r\n\r\n\tconst { isOpen, onOpen, onClose } = useDisclosure();\r\n\tconst [privateReason, setPrivateReason] = useState(\"\");\r\n\tconst [publicReason, setPublicReason] = useState(\"\");\r\n\tconst [notifyInterestedUsers, setNotifyInterestedUsers] = useState(true);\r\n\tconst [showConfirmationDelete, setShowConfirmationDelete] = useState<boolean>(false);\r\n\r\n\tconst handleToggleConfirmDelete = useCallback(\r\n\t\t(show: boolean) => () => setShowConfirmationDelete(show),\r\n\t\t[],\r\n\t);\r\n\r\n\t// populate form with any saved values from the app when it opens\r\n\tconst handleOpen = useCallback(() => {\r\n\t\tsetPrivateReason(app?.notNowDecision?.privateReason || \"\");\r\n\t\tsetPublicReason(app?.notNowDecision?.publicReason || \"\");\r\n\t\tsetNotifyInterestedUsers(true);\r\n\t\tonOpen();\r\n\t}, [app?.notNowDecision?.privateReason, app?.notNowDecision?.publicReason, onOpen]);\r\n\r\n\tconst handleSetNotifyInterestedUsers = useCallback((ev: ChangeEvent<HTMLInputElement>) => {\r\n\t\tsetNotifyInterestedUsers(ev.target.checked);\r\n\t}, []);\r\n\r\n\tconst handleSetPrivateReason = useCallback((ev: ChangeEvent<HTMLTextAreaElement>) => {\r\n\t\tsetPrivateReason(ev.target.value);\r\n\t}, []);\r\n\r\n\tconst handleSetPublicReason = useCallback((ev: ChangeEvent<HTMLTextAreaElement>) => {\r\n\t\tsetPublicReason(ev.target.value);\r\n\t}, []);\r\n\r\n\tconst handleMarkAsNotImplNowSuccess = useCallback<ISuccessHandler<typeof markAsNotImplementingNow>>(\r\n\t\t(updatedNotNowDetails, extras) => {\r\n\t\t\tonClose();\r\n\r\n\t\t\tif (successHandler) {\r\n\t\t\t\tsuccessHandler(updatedNotNowDetails);\r\n\t\t\t} else {\r\n\t\t\t\tconst [appId, orgId] = extras.params;\r\n\t\t\t\tupdateNotImplementingNowDetails(dispatch!, orgId, appId, updatedNotNowDetails);\r\n\t\t\t}\r\n\t\t},\r\n\t\t[dispatch, onClose, successHandler],\r\n\t);\r\n\r\n\tconst handleMarkAsNotImplFailure = useCallback(() => {\r\n\t\tif (failureHandler) {\r\n\t\t\tfailureHandler();\r\n\t\t\tonClose();\r\n\t\t}\r\n\t}, [failureHandler, onClose]);\r\n\r\n\tconst [savingState, saveNotImplNowDetails] = useAsync(markAsNotImplementingNow, {\r\n\t\texecuteImmediately: false,\r\n\t\tdisplayName: \"markAsNotImplementingNow\",\r\n\t\t// `extras` contains a `params` field which has the params passed to the API call\r\n\t\tonSuccess: (response, extras) => handleMarkAsNotImplNowSuccess(response, extras),\r\n\t\tonFailure: handleMarkAsNotImplFailure,\r\n\t});\r\n\r\n\tconst handleSaveNotImplNowDetails = useCallback(\r\n\t\t(deleted: boolean = false) => () =>\r\n\t\t\tsaveNotImplNowDetails(\r\n\t\t\t\tapp?.appId!,\r\n\t\t\t\torgId!,\r\n\t\t\t\tprivateReason,\r\n\t\t\t\tpublicReason,\r\n\t\t\t\tnotifyInterestedUsers,\r\n\t\t\t\tdeleted,\r\n\t\t\t),\r\n\t\t[app?.appId, notifyInterestedUsers, orgId, privateReason, publicReason, saveNotImplNowDetails],\r\n\t);\r\n\r\n\tconst handleConfirmDeleteClick = useCallback(() => {\r\n\t\tsetShowConfirmationDelete(false);\r\n\t\thandleSaveNotImplNowDetails(true)();\r\n\t}, [handleSaveNotImplNowDetails]);\r\n\r\n\tconst isSaving = isInFlight(savingState);\r\n\tconst hasError = failureHandler && lastExecutionErrored(savingState);\r\n\r\n\t//#endregion\r\n\r\n\tconst NowImplementingNowButton = buttonAs || WidgetActionButton;\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t<NowImplementingNowButton\r\n\t\t\t\tonClick={handleOpen}\r\n\t\t\t\tcolorScheme=\"red\"\r\n\t\t\t\ttitle={\r\n\t\t\t\t\thasSavedNotNowDetails\r\n\t\t\t\t\t\t? \"Update Not Implementing Now Details\"\r\n\t\t\t\t\t\t: \"Mark this product as not implementing now for your organization. Marking as not implementing now will prevent other people from your organization from nominating this product.\"\r\n\t\t\t\t}\r\n\t\t\t\tleftIcon={\r\n\t\t\t\t\t!excludeIcon && (\r\n\t\t\t\t\t\t<AiOutlineClockCircle\r\n\t\t\t\t\t\t\tsize={20}\r\n\t\t\t\t\t\t\tstyle={{ color: iconColor, paddingTop: \"2px\", paddingBottom: \"2px\" }}\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t\t{...rest}\r\n\t\t\t>\r\n\t\t\t\t{buttonText ? buttonText : \"Not Implementing Now\"}\r\n\t\t\t</NowImplementingNowButton>\r\n\t\t\t<Modal\r\n\t\t\t\tisOpen={isOpen}\r\n\t\t\t\tonClose={onClose}\r\n\t\t\t\tsize=\"2xl\"\r\n\t\t\t\tpreserveScrollBarGap\r\n\t\t\t\tisCentered\r\n\t\t\t\treturnFocusOnClose\r\n\t\t\t>\r\n\t\t\t\t<ModalOverlay />\r\n\t\t\t\t<ModalContent>\r\n\t\t\t\t\t<ModalHeader>Mark Not Implementing Now</ModalHeader>\r\n\t\t\t\t\t<ModalCloseButton />\r\n\t\t\t\t\t<ModalBody>\r\n\t\t\t\t\t\t<FormControl id=\"PrivateReason\">\r\n\t\t\t\t\t\t\t<FormLabel display=\"inline-block\" mr=\"0.5em\">\r\n\t\t\t\t\t\t\t\tPrivate Reason\r\n\t\t\t\t\t\t\t</FormLabel>\r\n\t\t\t\t\t\t\t<AOTooltip\r\n\t\t\t\t\t\t\t\thelptext={`Reason you're not implementing this product right now. This is only visible to users with can purchase security.`}\r\n\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t<BsFillQuestionCircleFill />\r\n\t\t\t\t\t\t\t</AOTooltip>\r\n\t\t\t\t\t\t\t<TextareaWithRemainingChars\r\n\t\t\t\t\t\t\t\tmaxChars={300}\r\n\t\t\t\t\t\t\t\tvalue={privateReason}\r\n\t\t\t\t\t\t\t\tonChange={handleSetPrivateReason}\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t</FormControl>\r\n\r\n\t\t\t\t\t\t<FormControl mt=\"2em\" id=\"PublicReason\">\r\n\t\t\t\t\t\t\t<Flex alignItems=\"center\">\r\n\t\t\t\t\t\t\t\t<FormLabel display=\"inline-block\" mr=\"0.5em\">\r\n\t\t\t\t\t\t\t\t\tPublic Reason\r\n\t\t\t\t\t\t\t\t</FormLabel>\r\n\t\t\t\t\t\t\t\t<AOTooltip\r\n\t\t\t\t\t\t\t\t\thelptext=\"Reason you're not implementing this product right now. This is visible to everyone from your organization.\"\r\n\t\t\t\t\t\t\t\t\tboxProps={{ marginBottom: \"10px\" }}\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t<BsFillQuestionCircleFill />\r\n\t\t\t\t\t\t\t\t</AOTooltip>\r\n\t\t\t\t\t\t\t\t<Spacer />\r\n\t\t\t\t\t\t\t\t<WarningTwoIcon color=\"red\" mr=\"2px\" w=\"1.25em\" h=\"1.25em\" />\r\n\t\t\t\t\t\t\t\t<Text as=\"span\" fontStyle=\"italic\" fontSize=\"0.85em\">\r\n\t\t\t\t\t\t\t\t\tThis is visible to anyone from your organization.\r\n\t\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t</Flex>\r\n\t\t\t\t\t\t\t<TextareaWithRemainingChars\r\n\t\t\t\t\t\t\t\tmaxChars={300}\r\n\t\t\t\t\t\t\t\tisRequired\r\n\t\t\t\t\t\t\t\tvalue={publicReason}\r\n\t\t\t\t\t\t\t\tonChange={handleSetPublicReason}\r\n\t\t\t\t\t\t\t\tisInvalid={!publicReason}\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t</FormControl>\r\n\r\n\t\t\t\t\t\t<FormControl mt=\"1.5em\" id=\"NotifyInterestedUser\">\r\n\t\t\t\t\t\t\t<Checkbox\r\n\t\t\t\t\t\t\t\tmr=\"0.5em\"\r\n\t\t\t\t\t\t\t\tisChecked={notifyInterestedUsers}\r\n\t\t\t\t\t\t\t\tonChange={handleSetNotifyInterestedUsers}\r\n\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\tNotify interested users\r\n\t\t\t\t\t\t\t</Checkbox>\r\n\t\t\t\t\t\t\t<AOTooltip helptext=\"Whether to notify users who've nominated this product that your organization is not planning on implementing it now, along with the public reason why.\">\r\n\t\t\t\t\t\t\t\t<BsFillQuestionCircleFill />\r\n\t\t\t\t\t\t\t</AOTooltip>\r\n\t\t\t\t\t\t</FormControl>\r\n\t\t\t\t\t</ModalBody>\r\n\r\n\t\t\t\t\t<ModalFooter>\r\n\t\t\t\t\t\t<VStack>\r\n\t\t\t\t\t\t\t<Box>\r\n\t\t\t\t\t\t\t\t{hasSavedNotNowDetails && (\r\n\t\t\t\t\t\t\t\t\t<Button\r\n\t\t\t\t\t\t\t\t\t\tcolorScheme=\"red\"\r\n\t\t\t\t\t\t\t\t\t\tmr={2}\r\n\t\t\t\t\t\t\t\t\t\tonClick={handleToggleConfirmDelete(true)}\r\n\t\t\t\t\t\t\t\t\t\tdisabled={isSaving}\r\n\t\t\t\t\t\t\t\t\t\ttitle={deleteNotNowHelptext}\r\n\t\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t\tRemove\r\n\t\t\t\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t\t<Button\r\n\t\t\t\t\t\t\t\t\tloadingText=\"Saving\"\r\n\t\t\t\t\t\t\t\t\tisLoading={isSaving}\r\n\t\t\t\t\t\t\t\t\tdisabled={isSaving || !publicReason}\r\n\t\t\t\t\t\t\t\t\ttitle={!publicReason ? \"Public reason is required to save\" : \"\"}\r\n\t\t\t\t\t\t\t\t\tcolorScheme=\"blue\"\r\n\t\t\t\t\t\t\t\t\tmr={2}\r\n\t\t\t\t\t\t\t\t\tonClick={handleSaveNotImplNowDetails()}\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\tSave\r\n\t\t\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t\t\t<Button onClick={onClose} disabled={isSaving}>\r\n\t\t\t\t\t\t\t\t\tCancel\r\n\t\t\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t\t</Box>\r\n\t\t\t\t\t\t\t{hasError && (\r\n\t\t\t\t\t\t\t\t<Box>\r\n\t\t\t\t\t\t\t\t\t<StatusAlert\r\n\t\t\t\t\t\t\t\t\t\tmessage=\"Error saving the last change to the server.\"\r\n\t\t\t\t\t\t\t\t\t\tstatus=\"error\"\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t</Box>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t</VStack>\r\n\t\t\t\t\t</ModalFooter>\r\n\t\t\t\t</ModalContent>\r\n\t\t\t</Modal>\r\n\t\t\t<ConfirmationModal\r\n\t\t\t\ttitle=\"Unmark product as Not Implementing Now\"\r\n\t\t\t\tmessage=\"Are you sure you want to unmark this product as 'Not Implementing Now' and allow users to nominate it again? Your organization's prior reasons for marking as 'Not Implementing Now' are still saved in the database but they will not be displayed on the website anymore if you continue.\"\r\n\t\t\t\tacceptCaption=\"Continue\"\r\n\t\t\t\tcancelCaption=\"Cancel\"\r\n\t\t\t\tisOpen={showConfirmationDelete}\r\n\t\t\t\tonCancel={handleToggleConfirmDelete(false)}\r\n\t\t\t\tonAccept={handleConfirmDeleteClick}\r\n\t\t\t/>\r\n\t\t</>\r\n\t);\r\n});\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file Summary of who marked the app as not implementing now, when, and why (used by the Nominated Apps widget)\r\n * @module Epic.AppOrchard.Dashboard.NotImplementingNowInfo\r\n */\r\n\r\nimport { TimeIcon, WarningTwoIcon } from \"@chakra-ui/icons\";\r\nimport { Box } from \"@chakra-ui/react\";\r\nimport { WidgetTag } from \"ao/components/Dashboard/widgetHelpers\";\r\nimport { INotImplementingNowDecision, IUserSecurity } from \"ao/types\";\r\nimport React, { FC, memo } from \"react\";\r\n\r\ninterface IProps {\r\n\t/** current app version ID */\r\n\tlatestAppVersionId: number;\r\n\tnotNowDecision: INotImplementingNowDecision;\r\n\tuserSecurity: IUserSecurity;\r\n}\r\n\r\n/** Summary of who marked the app as not implementing now, when, and why (used by the Nominated Apps widget) */\r\nexport const NotImplementingNowInfo: FC<IProps> = memo((props: IProps) => {\r\n\tconst { notNowDecision, userSecurity, latestAppVersionId } = props;\r\n\r\n\tconst isPriorVersion = latestAppVersionId !== notNowDecision.appVersionId;\r\n\r\n\treturn (\r\n\t\t<WidgetTag\r\n\t\t\tlabel=\"Not implementing now\"\r\n\t\t\ttooltipContent={\r\n\t\t\t\t<NotImplementingNowInfoBody\r\n\t\t\t\t\tlatestAppVersionId={latestAppVersionId}\r\n\t\t\t\t\tnotNowDecision={notNowDecision}\r\n\t\t\t\t\tuserSecurity={userSecurity}\r\n\t\t\t\t/>\r\n\t\t\t}\r\n\t\t\ticon={TimeIcon}\r\n\t\t\trightIcon={isPriorVersion ? WarningTwoIcon : undefined}\r\n\t\t\trightIconProps={isPriorVersion ? { w: 4, h: 4, color: \"yellow.500\" } : undefined}\r\n\t\t\ttooltipProps={{ w: { base: \"65vw\", lg: \"15vw\" }, maxW: { base: \"65vw\", lg: \"15vw\" } }}\r\n\t\t></WidgetTag>\r\n\t);\r\n});\r\n\r\nexport const NotImplementingNowInfoBody: FC<IProps> = memo((props: IProps) => {\r\n\tconst { notNowDecision, userSecurity, latestAppVersionId } = props;\r\n\r\n\tconst showPrivateReason =\r\n\t\t(userSecurity.canPurchase || userSecurity.isEpicUser) && notNowDecision.privateReason;\r\n\r\n\tconst showNotNowUserName =\r\n\t\t(userSecurity.canPurchase || userSecurity.isEpicUser) && notNowDecision.userName;\r\n\r\n\tconst isPriorVersion = latestAppVersionId !== notNowDecision.appVersionId;\r\n\r\n\treturn (\r\n\t\t<Box>\r\n\t\t\t<Box mb=\"0.5em\">\r\n\t\t\t\t{isPriorVersion && (\r\n\t\t\t\t\t<Box fontStyle=\"italic\" mb=\"0.5em\">\r\n\t\t\t\t\t\tThis decision was documented for a previous app version.\r\n\t\t\t\t\t</Box>\r\n\t\t\t\t)}\r\n\t\t\t\tMarked not implementing now {showNotNowUserName ? \"by \" + notNowDecision.userName : \"\"} on{\" \"}\r\n\t\t\t\t{new Date(notNowDecision.instant).toLocaleDateString()}{\" \"}\r\n\t\t\t</Box>\r\n\t\t\t{showPrivateReason && (\r\n\t\t\t\t<>\r\n\t\t\t\t\t<Box fontWeight=\"bold\">Private Reason: </Box>\r\n\t\t\t\t\t<Box mb=\"0.5em\">{notNowDecision.privateReason}</Box>\r\n\t\t\t\t</>\r\n\t\t\t)}\r\n\t\t\t{showPrivateReason && <Box fontWeight=\"bold\">Public Reason: </Box>}\r\n\t\t\t<Box>{notNowDecision.publicReason}</Box>\r\n\t\t</Box>\r\n\t);\r\n});\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file state/store for nominated apps widget\r\n * @module Epic.AppOrchard.State.NominatedApps\r\n */\r\n\r\nimport { buildSharedState } from \"@epic/react-redux-booster\";\r\nimport store from \"../../store\";\r\nimport { INominatedApp, INotImplementingNowDecision } from \"../../types\";\r\nimport { searchHasMatch } from \"../../utils/helpers\";\r\n\r\n/// TYPES ///\r\n\r\n/** Org specific info */\r\ninterface IOrgDetails {\r\n\thasSignedCurrentApiLicenseAgreement: boolean;\r\n\thasSignedAnyApiLicenseAgreement: boolean;\r\n}\r\n\r\nexport interface IState {\r\n\t// Map between the org ID and the nominated apps for a customer org\r\n\treadonly nominatedAppsForOrg: Map<number, INominatedApp[]> | undefined;\r\n\t// Whether nominated apps data has been loaded for a customer org\r\n\treadonly hasLoadedForOrg: Map<number, boolean> | undefined;\r\n\treadonly orgDetails: Map<number, IOrgDetails> | undefined;\r\n\treadonly participantTermsId: number | undefined;\r\n\treadonly apiLicenseAgreementId: number | undefined;\r\n}\r\n\r\n/**\r\n * Search params to identify the apps to select from the store\r\n */\r\ninterface INominatedAppsSelectorParams {\r\n\torgId: number;\r\n\tsearchTerm: string;\r\n}\r\n\r\n/// INIT ///\r\n\r\n/**\r\n * Returns an empty initial state\r\n */\r\nexport function getInitialState(): IState {\r\n\treturn {\r\n\t\thasLoadedForOrg: undefined,\r\n\t\tnominatedAppsForOrg: undefined,\r\n\t\tparticipantTermsId: undefined,\r\n\t\tapiLicenseAgreementId: undefined,\r\n\t\torgDetails: undefined,\r\n\t};\r\n}\r\n\r\n//#region REDUCERS\r\n\r\n/**\r\n * Make JS Date objects from string dates loaded from the server\r\n * @param app app to transform\r\n * @returns nominated apps with JS Date objects\r\n */\r\nfunction makeJSDates(app: INominatedApp): INominatedApp {\r\n\treturn {\r\n\t\t...app,\r\n\t\tnominations: app.nominations.map((nom) => {\r\n\t\t\treturn { ...nom, instant: new Date(nom.instant) };\r\n\t\t}),\r\n\t\tnotNowDecision: app.notNowDecision && {\r\n\t\t\t...app.notNowDecision,\r\n\t\t\tinstant: new Date(app.notNowDecision.instant),\r\n\t\t},\r\n\t};\r\n}\r\n\r\n/**\r\n * Update nominated apps for a customer org and nominated apps as loaded from server\r\n * @param state current state\r\n * @param params reducer params (org ID and apps to add)\r\n * @returns updated state\r\n */\r\nexport function updateNominatedAppsAfterLoad(\r\n\tstate: IState,\r\n\tparams: {\r\n\t\torgId: number;\r\n\t\tnominatedApps: INominatedApp[];\r\n\t\tparticipantTermsId: number;\r\n\t\tapiLicenseAgreementId: number | null;\r\n\t\thasSignedCurrentApiLicenseAgreement: boolean | null;\r\n\t\thasSignedAnyApiLicenseAgreement: boolean | null;\r\n\t},\r\n): IState {\r\n\tconst {\r\n\t\torgId,\r\n\t\tnominatedApps,\r\n\t\tparticipantTermsId,\r\n\t\tapiLicenseAgreementId,\r\n\t\thasSignedCurrentApiLicenseAgreement,\r\n\t\thasSignedAnyApiLicenseAgreement,\r\n\t} = params;\r\n\r\n\t// update state to indicate we've loaded data for this org\r\n\tconst loadedMap = state.hasLoadedForOrg\r\n\t\t? new Map<number, boolean>([...Array.from(state.hasLoadedForOrg), [orgId, true]])\r\n\t\t: new Map<number, boolean>([[orgId, true]]);\r\n\r\n\t// update state to indicate we've loaded data for this org\r\n\tconst orgDetails: IOrgDetails = {\r\n\t\thasSignedAnyApiLicenseAgreement: hasSignedAnyApiLicenseAgreement || false,\r\n\t\thasSignedCurrentApiLicenseAgreement: hasSignedCurrentApiLicenseAgreement || false,\r\n\t};\r\n\tconst orgDetailsMap = state.orgDetails\r\n\t\t? new Map<number, IOrgDetails>([...Array.from(state.orgDetails), [orgId, orgDetails]])\r\n\t\t: new Map<number, IOrgDetails>([[orgId, orgDetails]]);\r\n\r\n\tconst nomAppsEntryForOrg = nominatedApps.map((a) => makeJSDates(a));\r\n\r\n\t// update data loaded for the org\r\n\tconst nomAppsMap = state.nominatedAppsForOrg\r\n\t\t? new Map<number, INominatedApp[]>([\r\n\t\t\t\t...Array.from(state.nominatedAppsForOrg),\r\n\t\t\t\t[orgId, nomAppsEntryForOrg],\r\n\t\t ])\r\n\t\t: new Map<number, INominatedApp[]>([[orgId, nomAppsEntryForOrg]]);\r\n\r\n\treturn {\r\n\t\thasLoadedForOrg: loadedMap,\r\n\t\tnominatedAppsForOrg: nomAppsMap,\r\n\t\tparticipantTermsId: participantTermsId,\r\n\t\tapiLicenseAgreementId: apiLicenseAgreementId || undefined,\r\n\t\torgDetails: orgDetailsMap,\r\n\t};\r\n}\r\n\r\n/**\r\n * Add or update not implementing now details\r\n * @param state current state\r\n * @param params reducer params (customer org ID and apps to add)\r\n * @returns updated state\r\n */\r\nexport function updateNotImplementingNowDetails(\r\n\tstate: IState,\r\n\tparams: { appId: number; orgId: number; notNowDecision: INotImplementingNowDecision | null },\r\n): IState {\r\n\tconst { appId, orgId, notNowDecision } = params;\r\n\tconst currentApps = getAppsOfType(state, orgId, \"\", undefined);\r\n\tconst updatedApps = currentApps.map((app) =>\r\n\t\tapp.appId !== appId\r\n\t\t\t? app\r\n\t\t\t: {\r\n\t\t\t\t\t...app,\r\n\t\t\t\t\tnotNowDecision: notNowDecision\r\n\t\t\t\t\t\t? {\r\n\t\t\t\t\t\t\t\tprivateReason: notNowDecision.privateReason,\r\n\t\t\t\t\t\t\t\tpublicReason: notNowDecision.publicReason,\r\n\t\t\t\t\t\t\t\tuserName: notNowDecision.userName,\r\n\t\t\t\t\t\t\t\tinstant: new Date(notNowDecision.instant),\r\n\t\t\t\t\t\t\t\tappVersionId: notNowDecision.appVersionId,\r\n\t\t\t\t\t\t }\r\n\t\t\t\t\t\t: null,\r\n\t\t\t },\r\n\t);\r\n\r\n\treturn {\r\n\t\t...state,\r\n\t\tnominatedAppsForOrg: new Map<number, INominatedApp[]>([\r\n\t\t\t...Array.from(state.nominatedAppsForOrg!),\r\n\t\t\t[orgId, updatedApps],\r\n\t\t]),\r\n\t};\r\n}\r\n\r\n/**\r\n * Remove app from the set of nominated apps after the customer has requested a download from the vendor\r\n * @param state current state\r\n * @param params reducer params (customer org ID and client app ID)\r\n * @returns updated state\r\n */\r\nexport function removeAppAfterDownloadRequest(\r\n\tstate: IState,\r\n\tparams: { appId: number; orgId: number },\r\n): IState {\r\n\tconst { appId, orgId } = params;\r\n\tconst currentApps = getAppsOfType(state, orgId, \"\", undefined);\r\n\tconst updatedApps = currentApps.filter((app) => app.appId !== appId);\r\n\r\n\treturn {\r\n\t\t...state,\r\n\t\tnominatedAppsForOrg: new Map<number, INominatedApp[]>([\r\n\t\t\t...Array.from(state.nominatedAppsForOrg!),\r\n\t\t\t[orgId, updatedApps],\r\n\t\t]),\r\n\t};\r\n}\r\n\r\n/**\r\n * Update state when org signed current API license terms\r\n * @param state current state\r\n * @param orgId customer org ID\r\n * @returns updated state\r\n */\r\nexport function updateOrgSignedTerms(state: IState, orgId: number): IState {\r\n\tconst orgDetails = state.orgDetails?.get(orgId);\r\n\tif (!orgDetails) {\r\n\t\treturn state;\r\n\t}\r\n\r\n\tconst updatedOrgDetails: IOrgDetails = {\r\n\t\t...orgDetails,\r\n\t\thasSignedCurrentApiLicenseAgreement: true,\r\n\t\thasSignedAnyApiLicenseAgreement: true,\r\n\t};\r\n\r\n\treturn {\r\n\t\t...state,\r\n\t\torgDetails: new Map<number, IOrgDetails>([\r\n\t\t\t...Array.from(state.orgDetails!),\r\n\t\t\t[orgId, updatedOrgDetails],\r\n\t\t]),\r\n\t};\r\n}\r\n\r\n//#endregion\r\n\r\n//#region SELECTORS\r\n\r\n/**\r\n * Check whether data has been loaded for a customer org\r\n * @param state current state\r\n * @param orgId: customer org id\r\n * @returns\r\n */\r\nexport function getHasLoaded(state: IState, orgId: number): boolean {\r\n\treturn state.hasLoadedForOrg !== undefined && state.hasLoadedForOrg.get(orgId) === true;\r\n}\r\n\r\n/**\r\n * Get org level information ( same across all apps for an org )\r\n * @param state current state\r\n * @returns\r\n */\r\nexport function getStaticOrgDetails(\r\n\tstate: IState,\r\n\torgId: number,\r\n): [\r\n\tparticipantTermsId: number | undefined,\r\n\tapiLicenseAgreementId: number | undefined,\r\n\thasSignedAnyApiLicenseAgreement: boolean | undefined,\r\n\thasSignedCurrentApiLicenseAgreement: boolean | undefined,\r\n] {\r\n\tif (!state.hasLoadedForOrg) {\r\n\t\treturn [undefined, undefined, undefined, undefined];\r\n\t}\r\n\tconst orgDetails = state.orgDetails?.get(orgId);\r\n\treturn [\r\n\t\tstate.participantTermsId,\r\n\t\tstate.apiLicenseAgreementId,\r\n\t\torgDetails?.hasSignedAnyApiLicenseAgreement,\r\n\t\torgDetails?.hasSignedCurrentApiLicenseAgreement,\r\n\t];\r\n}\r\n\r\nfunction hasDataForOrg(state: IState, orgId: number): boolean {\r\n\treturn state.nominatedAppsForOrg !== undefined && state.nominatedAppsForOrg.get(orgId) !== undefined;\r\n}\r\n\r\n/**\r\n * Helper to filter apps by search term\r\n * @param searchTerm search term to filter apps on\r\n * @param app nominated app being considered for inclusion in results\r\n * @returns true if passes filter else false\r\n */\r\nfunction filterBySearchTerm(searchTerm: string, app: INominatedApp): boolean {\r\n\treturn (\r\n\t\tsearchHasMatch(searchTerm, app.appName) ||\r\n\t\tsearchHasMatch(searchTerm, app.appOrgName) ||\r\n\t\tsearchHasMatch(searchTerm, app.prodClientId) ||\r\n\t\tsearchHasMatch(searchTerm, app.nonProdClientId)\r\n\t);\r\n}\r\n\r\n/**\r\n * Shared helper that filters to nominated apps of a given type + search term filtering\r\n *\r\n * Checks if data has been loaded for the org too\r\n * @param state current state\r\n * @param orgId customer org ID\r\n * @param searchTerm search term to further filter matching apps\r\n * @param filterFn function to filter to type of nominated app\r\n * @returns list of nominated apps matching filters\r\n */\r\nfunction getAppsOfType(\r\n\tstate: IState,\r\n\torgId: number,\r\n\tsearchTerm: string,\r\n\tfilterFn: ((app: INominatedApp) => boolean) | undefined,\r\n): INominatedApp[] {\r\n\tif (!getHasLoaded(state, orgId) || !hasDataForOrg(state, orgId)) {\r\n\t\treturn [];\r\n\t}\r\n\tlet apps = state.nominatedAppsForOrg!.get(orgId)!;\r\n\tif (filterFn && apps.length > 0) {\r\n\t\tapps = apps.filter(filterFn);\r\n\t}\r\n\r\n\tif (searchTerm && apps.length > 0) {\r\n\t\tapps = apps.filter((a) => filterBySearchTerm(searchTerm, a));\r\n\t}\r\n\r\n\treturn apps;\r\n}\r\n\r\n/**\r\n * Sort needs review apps by number of nominations and then instant of nomination\r\n * @param a first app\r\n * @param b second app\r\n * @returns standard sort number value\r\n */\r\nfunction sortNeedsReviewApps(a: INominatedApp, b: INominatedApp): number {\r\n\t// sort by number of nominations first if they're different\r\n\tif (a.nominations.length !== b.nominations.length) {\r\n\t\treturn b.nominations.length - a.nominations.length;\r\n\t}\r\n\tconst aMostRecentNomInst = Math.max.apply(\r\n\t\tnull,\r\n\t\ta.nominations.map((n) => n.instant.getTime()),\r\n\t);\r\n\tconst bMostRecentNomInst = Math.max.apply(\r\n\t\tnull,\r\n\t\tb.nominations.map((n) => n.instant.getTime()),\r\n\t);\r\n\treturn bMostRecentNomInst - aMostRecentNomInst;\r\n}\r\n\r\n/**\r\n * Get nominated apps for a customer (that ARE NOT marked as not implementing now)\r\n * @param state current state\r\n * @param params filter params\r\n */\r\nexport function getNeedsReviewApps(state: IState, params: INominatedAppsSelectorParams): INominatedApp[] {\r\n\tconst { orgId, searchTerm } = params;\r\n\tconst apps = getAppsOfType(\r\n\t\tstate,\r\n\t\torgId,\r\n\t\tsearchTerm,\r\n\t\t(a) => a.nominations.length > 0 && a.notNowDecision === null,\r\n\t);\r\n\treturn apps.sort(sortNeedsReviewApps);\r\n}\r\n\r\n/**\r\n * Get nominated apps that ARE marked as not implementing now\r\n * @param state current state\r\n * @param params filter params\r\n */\r\nexport function getNotImplementingNowApps(\r\n\tstate: IState,\r\n\tparams: INominatedAppsSelectorParams,\r\n): INominatedApp[] {\r\n\tconst { orgId, searchTerm } = params;\r\n\tconst apps = getAppsOfType(state, orgId, searchTerm, (a) => a.notNowDecision !== null);\r\n\treturn apps.sort((a, b) => b.notNowDecision!.instant.getTime() - a.notNowDecision!.instant.getTime());\r\n}\r\n\r\n//#endregion\r\n\r\n/// BUILD IT ///\r\n\r\nconst builtState = buildSharedState({\r\n\tinit: getInitialState,\r\n\treducers: {\r\n\t\tupdateNominatedAppsAfterLoad,\r\n\t\tupdateNotImplementingNowDetails,\r\n\t\tremoveAppAfterDownloadRequest,\r\n\t\tupdateOrgSignedTerms,\r\n\t},\r\n\tselectors: {\r\n\t\tgetHasLoaded,\r\n\t\tgetStaticOrgDetails,\r\n\t\tgetNeedsReviewApps,\r\n\t\tgetNotImplementingNowApps,\r\n\t},\r\n});\r\nstore.addSharedState(builtState.sharedState, \"nominatedApps\");\r\n\r\nexport const { actionCreators: nominatedAppsActions, useSharedState: useNominatedAppsState } = builtState;\r\n","/**\r\n * @copyright Copyright 2021 Epic Systems Corporation\r\n * @file nominated apps store updater methods\r\n * @module Epic.AppOrchard.StoreMethods.NominatedApps\r\n */\r\n\r\nimport { IDispatch } from \"@epic/react-redux-booster\";\r\nimport { nominatedAppsActions } from \"../state/widgets/nominatedApps\";\r\nimport { INominatedApp, INotImplementingNowDecision } from \"../types\";\r\n\r\n/**\r\n * Update store with nominated apps after loading from server\r\n * @param dispatch for useDispatch\r\n * @param orgId customer org id\r\n * @param nominatedApps nominated apps for customer org\r\n */\r\nexport function updateNominatedAppsAfterLoad(\r\n\tdispatch: IDispatch,\r\n\torgId: number,\r\n\tnominatedApps: INominatedApp[],\r\n\tparticipantTermsId: number,\r\n\tapiLicenseAgreementId: number | null,\r\n\thasSignedAnyApiLicenseAgreement: boolean,\r\n\thasSignedCurrentApiLicenseAgreement: boolean,\r\n) {\r\n\tdispatch(\r\n\t\tnominatedAppsActions.updateNominatedAppsAfterLoad({\r\n\t\t\torgId,\r\n\t\t\tnominatedApps,\r\n\t\t\tparticipantTermsId,\r\n\t\t\tapiLicenseAgreementId,\r\n\t\t\thasSignedAnyApiLicenseAgreement,\r\n\t\t\thasSignedCurrentApiLicenseAgreement,\r\n\t\t}),\r\n\t);\r\n}\r\n\r\n/**\r\n * Update not implementing now information\r\n * @param dispatch for useDispatch\r\n * @param appId client app id\r\n * @param orgId customer org id\r\n * @param notNowDecision not implementing now details\r\n */\r\nexport function updateNotImplementingNowDetails(\r\n\tdispatch: IDispatch,\r\n\torgId: number,\r\n\tappId: number,\r\n\tnotNowDecision: INotImplementingNowDecision | null,\r\n) {\r\n\tdispatch(nominatedAppsActions.updateNotImplementingNowDetails({ appId, orgId, notNowDecision }));\r\n}\r\n\r\n/**\r\n * Remove app from the set of nominated apps after the customer has requested a download from the vendor\r\n * @param dispatch for useDispatch\r\n * @param appId client app id\r\n * @param orgId customer org id\r\n */\r\nexport function removeAppAfterDownloadRequest(dispatch: IDispatch, orgId: number, appId: number) {\r\n\tdispatch(nominatedAppsActions.removeAppAfterDownloadRequest({ appId, orgId }));\r\n}\r\n\r\n/** Update state when org signed current API license terms\r\n * @param state current state\r\n * @param orgId customer org ID\r\n */\r\nexport function updateOrgSignedTerms(dispatch: IDispatch, orgId: number) {\r\n\tdispatch(nominatedAppsActions.updateOrgSignedTerms(orgId));\r\n}\r\n"],"names":["getEmptyFilterParamsForOrg","orgId","searchTerm","currentUserId","createdByCurrentUserOnly","changeRequestsOnly","includeAllRelatedOrgApps","getHasLoaded","state","undefined","hasLoadedForOrg","get","getAppsOfType","filterParams","filterFn","appsForOrg","hasDataForOrg","apps","length","filter","a","createdBy","license","changeRequestType","owningOrgName","isActivatedInNonProd","isActivatedInProd","app","searchHasMatch","appName","prodClientId","nonProdClientId","filterBySearchTerm","builtState","buildSharedState","init","orgCurrentEpicVersions","isLocalJKUWarningEnabledForFeb24","reducers","updateAppsAfterLoad","params","orgCurrentEpicVersion","isLocalJKUWarningEnabled","loadedMap","Map","Array","from","appsEntryForOrg","map","createdOn","Date","lic","nonProdLicensedOn","prodLicensedOn","changeRequestedOn","makeAppJSDates","markAsInternal","appId","updatedApps","status","ClientApplicationStatus","Internal","updateChangeRequest","changeType","comment","currentApps","isDelete","changeRequestComment","changeRequestedByUserName","selectors","getDraftApps","sort","b","localeCompare","getAppsActivatedForTesting","getAppsActivatedForProd","getOrgCurrentEpicVersion","getIsLocalJKUWarningEnabledForFeb24","store","addSharedState","sharedState","actionCreators","homegrownAppsActions","useSharedState","useHomegrownAppsState","dispatch","formattedChangeRequest","CustomerAppChangeRequestType","NonProdActivation","ProdActivation","NonProdCredentialUpdate","ProdCredentialUpdate","HomegrownAppRow","memo","props","_app$license$changeRe","userSecurity","baseUrl","isRelatedOrgApp","appBaseUrl","isEpicCustomer","concat","isEpicAdministrator","isSuperAdministrator","hasAppUrl","statsUrl","metricsUrl","isNewestAppVersion","newestAppVersion","isLockedDown","Active","attestation","setAttestation","useState","siteInfo","useSiteInfoState","getState","licenseModel","useMemo","CustomerAppLicense","hasCreds","HasSavedCredsAnyEnv","isNullOrEmpty","nonProdJsonWebKeySetUrl","prodJsonWebKeySetUrl","hasBottomContent","hasApiStatsForOrg","hasApiMetricsForOrg","handleMarkInternal","useCallback","handleUpdateChangeRequest","changeComment","handleUpdateLicense","response","homegrownApps","attestationLoadingState","useAsync","getAttestation","executeImmediately","isCustomerAppAttestationEnabled","displayName","onSuccess","initialArguments","creationInfo","createdByUserName","toLocaleDateString","nonProdActivationInfo","nonProdLicensedByUserName","prodActivationInfo","prodLicensedByUserName","appIsNotActivated","isAttestationLoading","isInFlight","_jsx","_Fragment","children","WidgetAppRow","subtitle","_jsxs","Box","linkUrl","linkTitle","belowLogoContent","AppStatusTag","size","additionalAppInfo","VStack","spacing","width","WidgetTag","w","label","tooltipContent","UnorderedList","ListItem","icon","CalendarIcon","mt","BiMessageRoundedDetail","iconProps","h","marginInlineEnd","tooltipProps","base","lg","maxW","bottomContent","NewVersionLink","newVersionUrl","newestAppId","isOwnApp","title","GiNewShoot","style","display","marginRight","color","AppCredentialsLink","epicVersion","testJwtSigningPublicKeyThumbprint","prodJwtSigningPublicKeyThumbprint","testClientSecretHash","prodClientSecretHash","testPublicKeyBlobIsCSP","prodPublicKeyBlobIsCSP","AOLink","url","target","ImStatsBars","IoSpeedometerOutline","actions","MarkInternalButton","appStatus","successHandler","buttonAs","WidgetActionButton","hasApiContextWarning","hasOutOfContextAPIs","hasApiContextWarningOverride","hasApiContextValidationOverride","canActivateClients","UpdateCustomerAppLicenseButton","appUsesOAuth2","useOAuth2","appConsumerType","consumerType","appIsConfidentialClient","isConfidentialClient","envType","EnvironmentType","NonProd","updateLicenseApi","updateCustomerAppLicenseState","appJsonWebKeySetUrl","publicKeysAllowed","getsAppLicensesFromOrganization_Name","skipAttestation","isLoading","Prod","RequestCustomerAppChangeButton","getNumFiltersApplied","_len","arguments","args","_key","HomegrownAppsWidget","isExpanded","onFiltersUpdate","onNumFiltersAppliedUpdate","numFiltersApplied","setSearchTerm","handleChangeSearchTerm","newSearchTerm","setCreatedByCurrentUserOnly","setChangeRequestsOnly","setIncludeAllRelatedOrgApps","handleCreatedByCurrentUserChecked","ev","createdByCurrentUserChecked","checked","handleChangeRequestsOnlyChecked","changeRequestsOnlyChecked","handleIncludeAllRelatedOrgAppsChecked","getBaseUrl","entriesPerPage","config","Dashboard","WidgetAppRowsPerPage","useDispatch","hasLoaded","searchParams","userId","draftApps","activatedForTesting","activatedForProd","currentEpicVersion","handleAppsLoadedSuccess","extras","LoadingPlaceholder","loadApps","getHomegrownApps","AsyncPlaceholder","filters","Checkbox","isChecked","onChange","ml","isEpicUser","canViewAllRelatedOrgApps","useEffect","tabs","tabName","countPrefix","helptext","content","WidgetTable","noRecordsMessage","SearchInput","placeholder","onChangeCallback","inputGroupProps","mb","inProgressIndicator","WidgetSpinner","errorMessage","useLastRequestForErrors","Text","as","mr","TabbedSection","makeJSDates","downloadRequest","userName","instant","appOrgName","descriptor","updateInstallStatus","newStatus","installStatus","addRequestedApp","appsMap","getNotStartedApps","downloadApprovedStatus","DownloadApprovedStatus","Approved","NonProdOnly","InstallStatus","NotStarted","getWaitingOnVendorApps","Unapproved","getImplementingApps","InProgress","inProgressAppsActions","useInProgressAppsState","markedLiveOn","clearLoaded","loadedForOrg","getAllApps","getAppsWithoutReviews","numReviewsForOrg","getNumAppsLiveInLastXMonths","monthsAgo","today","xMonthsAgoInst","getFullYear","getMonth","getDay","getTime","liveAppsActions","useLiveAppsState","DownloadApprovedInfo","enabledForProdOnly","CheckIcon","InProgressAppRow","_app$appOrgName","_app$appOrgName2","_app$appOrgName3","marketplaceUrl","showroomUrl","downloadUrl","tesseractLogo","isUnapproved","hasTcPackages","turboChargerDocumentIds","implementationGuideUrl","downloadPageUrl","isAvailableInGallery","newestVersionDownloadPageUrl","isNewestVersionAvailableInGallery","appLinkRef","setAppLinkRef","handleSetAppLinkRef","linkRef","handleUpdateInstallStatusSuccess","updateInstallStatusInStore","Live","onLinkRefCreated","tesseractEnabled","Image","src","alt","DownloadBuildIcon","List","StarIcon","ImplementationGuideLink","DownloadBuildLink","showIcon","showWarningIcon","canPurchase","ContactButton","contactApi","badgerAuthor","apiArgs","buttonCaption","buttonNotContactedHelptext","successMessage","confirmModalTitle","confirmModalPrompt","finalFocusRef","EditableInstallStatus","buttonsAs","deactivationWarning","InProgressAppsWidget","onSubtitleUpdate","waitingForVendorApps","notStartedApps","implementingApps","handleAppsLoaded","inProgressApps","getInProgressApps","LiveAppRow","isGalleryEnabled","markedLiveByInfo","markedLiveAutomatically","markedLiveByUserName","markedLiveInfo","numReviews","middleColumnContent","LiveAppsWidget","monthsAgoForLiveAppsHeader","MonthsAgoForLiveAppsHeader","allApps","numApsLiveInLastXMonths","liveApps","getLiveApps","SiteName","NominatedAppRow","participantTermsId","installingLogo","liveLogo","showingOrgsModal","setShowingOrgsModal","orgsModalEnvType","setOrgsModalEnvType","orgsModalTitle","orgNameList","sharedInstallingOrgNames","sharedLiveOrgNames","otherOrgsMessage","totalOrgs","numOrgNames","numOtherOrgs","getOtherOrgsMessage","numInstallingOrgs","numLiveOrgs","hasInstallingOrgNames","hasLiveOrgNames","handleShowOrgsModal","handleToggleOrgsModal","show","installingOrgsHelptext","liveOrgsHelptext","hasDownloadableBuild","NominationInfo","latestAppVersionId","nominations","notNowDecision","NotImplementingNowInfo","NominatedAppsButtons","Wrap","WrapItem","WidgetAppBadge","asButton","buttonProps","onClick","value","toString","useHoverTooltip","Modal","isOpen","onClose","ModalOverlay","ModalContent","ModalHeader","ModalCloseButton","ModalBody","pt","orgName","index","fontWeight","ModalFooter","Button","colorScheme","leftIcon","BiCheckCircle","textDecoration","_hover","background","contactAuthor","MarkNowImplementingNowButton","rest","showUserName","some","n","nominationSummary","nom","isPriorVersion","appVersionId","fontStyle","fontSize","NominatedAppsWidget","useNominatedAppsState","getStaticOrgDetails","needsReviewApps","getNeedsReviewApps","notNowApps","getNotImplementingNowApps","handleNominatedAppsLoaded","updateNominatedAppsAfterLoad","nominatedApps","apiLicenseAgreementId","hasSignedAnyApiLicenseAgreement","hasSignedCurrentApiLicenseAgreement","loadNominatedApps","getNominatedApps","async","getAvailableDashboards","api","saveDashboardPreferences","dashboardDescriptor","prefs","post","Descriptor","WidgetPreferences","setDashboardAsDefault","markAsNotImplementingNow","_orgId","privateReason","publicReason","notifyInterestedUsers","deleted","AppId","PrivateReason","PublicReason","NotifyInterestedUsers","Deleted","data","getDefinedWidgets","variant","whiteSpace","minH","pb","SimpleGrid","columns","GridItem","colSpan","Flex","justify","Center","height","minWidth","minW","bg","p","borderRadius","AOTooltip","thumbnailUrl","fallbackThumbnailUrl","thumbnailColor","NumAppThumbnailColors","isMobile","useBreakpointValue","useRef","backgroundColor","m","border","AspectRatio","ratio","flex","fallbackSrc","childrenWithoutFragment","HStack","ref","textAlign","Divider","Spinner","role","borderWidth","VisuallyHidden","entriesToShowPerPage","expandedHeight","xl","React","count","PaginatedList","overflowX","rightIcon","rightIconProps","tag","Tag","TagLeftIcon","TagLabel","TagRightIcon","boxProps","_app$notNowDecision3","_app$notNowDecision4","failureHandler","interestedCount","buttonText","excludeIcon","iconColor","hasSavedNotNowDetails","hasNominations","deleteNotNowHelptext","onOpen","useDisclosure","setPrivateReason","setPublicReason","setNotifyInterestedUsers","showConfirmationDelete","setShowConfirmationDelete","handleToggleConfirmDelete","handleOpen","_app$notNowDecision","_app$notNowDecision2","handleSetNotifyInterestedUsers","handleSetPrivateReason","handleSetPublicReason","handleMarkAsNotImplNowSuccess","updatedNotNowDetails","updateNotImplementingNowDetails","handleMarkAsNotImplFailure","savingState","saveNotImplNowDetails","onFailure","handleSaveNotImplNowDetails","handleConfirmDeleteClick","isSaving","hasError","lastExecutionErrored","NowImplementingNowButton","AiOutlineClockCircle","paddingTop","paddingBottom","preserveScrollBarGap","isCentered","returnFocusOnClose","FormControl","id","FormLabel","BsFillQuestionCircleFill","TextareaWithRemainingChars","maxChars","alignItems","marginBottom","Spacer","WarningTwoIcon","isRequired","isInvalid","disabled","loadingText","StatusAlert","message","ConfirmationModal","acceptCaption","cancelCaption","onCancel","onAccept","NotImplementingNowInfoBody","TimeIcon","showPrivateReason","showNotNowUserName","nominatedAppsForOrg","sortNeedsReviewApps","aMostRecentNomInst","Math","max","apply","orgDetails","orgDetailsMap","nomAppsEntryForOrg","removeAppAfterDownloadRequest","updateOrgSignedTerms","_state$orgDetails","updatedOrgDetails","_state$orgDetails2","nominatedAppsActions"],"sourceRoot":""}