1 |
- {"version":3,"file":"1410.d10eb8a876bffea945fd.js","mappings":"qWAwBA,MAAMA,EAAkB,IAClBC,EAAkB,IAClBC,EAAkB,EAClBC,EAAiB,KAuChB,SAASC,EAAcC,GAC5B,MAAMC,EAAiB,GACvB,IAAK,MAAMC,KAASF,EAClB,GAAIE,EAAMC,UAAYD,EAAME,QAAUF,EAAME,OAAOC,OAAS,EAAG,CAC7D,MAAMC,EAAiBJ,EAAME,OAAOG,QAAQC,GAAUA,EAAML,WAAUM,KAAKD,GAAUA,EAAME,OACvFJ,EAAeD,OAAS,EAC1BJ,EAAeU,KAAM,GAAET,EAAMQ,UAAUJ,EAAeG,IAAIG,EAAAA,IAAiCC,KAAK,SAC7D,IAA1BP,EAAeD,QACxBJ,EAAeU,KAAM,GAAET,EAAMQ,UAASI,EAAAA,EAAAA,IAAgCR,EAAe,QAI3F,MAAO,CAAC,IAAKL,EAAeY,KAAK,KAAM,KAAKA,KAAK,IAqG5C,MAAME,UAAiCC,EAAAA,UAA4C,iDAClE,CACpBhB,OAAQ,GACRiB,WAAY,GACZC,OAAQ,QACRC,MAAO,GACPC,iBAAkB,KANoE,yBAStEC,IAChBC,KAAKC,SAAS,CAAEN,WAAYI,EAAMG,OAAOhB,WAV6C,8BAalE,MACpBiB,EAAAA,EAAAA,mBAAkB,kCAAmC,CACnDC,IAAKJ,KAAKK,MAAMD,IAChBE,UAAW,mBAEb,MAAMC,EAAW9B,EAAcuB,KAAKQ,MAAM9B,QAC1CsB,KAAKK,MAAMI,SAASF,MAnBkE,iCAsB/D,MACvBJ,EAAAA,EAAAA,mBAAkB,kCAAmC,CACnDC,IAAKJ,KAAKK,MAAMD,IAChBE,UAAW,uBAEb,MACMI,EAAS,QADEjC,EAAcuB,KAAKQ,MAAM9B,wBAE1CsB,KAAKK,MAAMI,SAASC,MA7BkE,uBAgCzE,MACbP,EAAAA,EAAAA,mBAAkB,kCAAmC,CACnDC,IAAKJ,KAAKK,MAAMD,IAChBE,UAAW,gBAEbN,KAAKC,UAAUO,IASN,CAAE9B,OARyB8B,EAAM9B,OAAOS,KAAKP,GAAD,iBAC9CA,EAD8C,CAEjDE,YAAQ6B,EACR9B,UAAU,EACV+B,SAAS,EACTC,QAAQ,EACRC,YAAQH,MAEOhB,WAAY,GAAIC,OAAQ,GAAIC,MAAO,GAAIC,iBAAkB,OAE5EE,KAAKK,MAAMU,0BAhD2E,uBAmDzE,CAAC3B,EAAcF,EAA2Ba,KACvD,MAAMnB,EAAQoB,KAAKQ,MAAM9B,OAAOsC,MAAMC,GAAMA,EAAE7B,OAASA,IACvD,IAAKR,EACH,OAGF,MAAMC,GAAYD,EAAMC,SACxB,IAAIqC,EAAsC,CAAErC,SAAAA,GAC5C,GAAID,EAAME,SAAWD,EAAU,CAE7B,MAAMC,EAASF,EAAME,OAAOK,KAAKD,GAAD,iBAAiBA,EAAjB,CAAwBL,UAAU,MAClEqC,EAAY,OAAH,UAAQA,EAAR,CAAmBJ,OAAQ,EAAGhC,OAAAA,IAGzCkB,KAAKC,SAAS,CAAEN,WAAY,KAC5BK,KAAKmB,iBAAiB/B,EAAM8B,EAAW,IAAI,IAAMlB,KAAKoB,oBAAoBhC,QAlEY,uBAqEzE,CAACA,EAAcF,EAA2Ba,KACvD,MAAMnB,EAAQoB,KAAKQ,MAAM9B,OAAOsC,MAAMC,GAAMA,EAAE7B,OAASA,IACvD,IAAKR,IAAUA,EAAME,OACnB,OAGFkB,KAAKC,SAAS,CAAEN,WAAY,KAE5B,MAAMb,EAASF,EAAME,OAAOK,KAAKkC,GAAD,iBAAaA,EAAb,CAAgBxC,SAAUwC,EAAEjC,OAASF,GAASmC,EAAExC,SAAWwC,EAAExC,aAC7FmB,KAAKmB,iBAAiB/B,EAAM,CAAEN,OAAAA,GAAU,IAAI,IAAMkB,KAAKsB,YAAYlC,QA9EmB,0BAiFtE,KAChB,MAAMmB,EAAW9B,EAAcuB,KAAKQ,MAAM9B,QAC1CsB,KAAKuB,iBAAiBhB,MAnFgE,sBAmJzEiB,IACb,MAAMjB,EAAW9B,EAAcuB,KAAKQ,MAAM9B,QAC1C,GAAI6B,IAAa/B,EAAgB,CAE/B,MAAME,EAA4BsB,KAAKQ,MAAM9B,OAAOS,KAAKP,GACvD,iBAAYA,EAAZ,CAAmBkC,OAAQ,EAAGhC,YAAQ6B,EAAWE,QAAQ,MAE3Db,KAAKC,SAAS,CAAEvB,OAAAA,IAAU,KAExBsB,KAAKQ,MAAM9B,OAAO+C,SAAS7C,GAAUA,EAAMC,UAAYmB,KAAK0B,YAAY9C,EAAMQ,KAAMmB,aAItFP,KAAK2B,YAAYpB,EAAUiB,MA1E/BL,iBAAiB/B,EAAcwC,GAAuE,IAA9BhC,EAA8B,uDAArB,GAAIiC,EAAiB,uCACpG7B,KAAKC,UAAUO,IACb,MAAM9B,EAA4B8B,EAAM9B,OAAOS,KAAKP,GAC9CA,EAAMQ,OAASA,EACjB,iBAAYR,EAAUgD,GAEjBhD,IAGHiB,EAAQD,EAAS,GAAKY,EAAMX,MAClC,MAAO,CAAEnB,OAAAA,EAAQkB,OAAAA,EAAQC,MAAAA,EAAOC,iBAAkB,MACjD+B,GAGLC,oBACE,MAAM,iBAAEC,EAAF,WAAoBC,EAAazD,EAAjC,eAAkD0D,GAAmBjC,KAAKK,MAChF,GAAI0B,EAAkB,CACpB,MAAMpD,EAA2BsD,EACjCF,EAAiBG,QAAQC,MAAK,KAC5B,IAAIC,EAAsBL,EAAiBM,eAC3C,GAAID,EAAUrD,OAASV,EAAiB,CACtC,MAAMwB,EAAS,+CAA4DuC,EAAUrD,UACrFqD,EAAYA,EAAUE,MAAM,EAAGjE,GAC/B2B,KAAKC,SAAS,CAAEJ,MAAAA,IAGlB,MAAMnB,EAA4B0D,EAAUjD,KAAI,CAACP,EAAO2D,EAAGC,KAAX,CAC9CpD,KAAMR,EACNC,SAAW2D,EAAIzD,QAAUiD,GAAwC,IAA1BrD,EAAeI,QAAiBJ,EAAe8D,SAAS7D,GAC/FgC,SAAS,MAGXZ,KAAKC,SAAS,CAAEvB,OAAAA,IAAU,KACxBsB,KAAKQ,MAAM9B,OAAO+C,SAAS7C,IACrBA,EAAMC,UACRmB,KAAK0B,YAAY9C,EAAMQ,KAAMZ,aAQzC4C,oBAAoBhC,GAClB,MAAMR,EAAQoB,KAAKQ,MAAM9B,OAAOsC,MAAMC,GAAMA,EAAE7B,OAASA,IACvD,IAAKR,EACH,OAEF,MAAMD,EAAiBqB,KAAKQ,MAAM9B,OAAOO,QAAQL,GAAUA,EAAMC,WAAUM,KAAKP,GAAUA,EAAMQ,OAChGY,KAAKK,MAAMqC,oBAAoB/D,GAC3BC,EAAMC,SAEHD,EAAME,QACTkB,KAAK0B,YAAYtC,EAAMX,EAAcuB,KAAKQ,MAAM9B,SAIlDsB,KAAKsB,cAqBQ,kBAAClC,EAAcmB,GAC9B,MAAM,iBAAEwB,GAAqB/B,KAAKK,MAClCL,KAAKmB,iBAAiB/B,EAAM,CAAEwB,SAAS,GAAS,uBAAsBxB,KACtE,IACE,IAAIuD,QAAkBZ,EAAiBa,eAAexD,GAEtD,GAAImB,IAAa9B,EAAcuB,KAAKQ,MAAM9B,QAExC,YADAsB,KAAKmB,iBAAiB/B,EAAM,CAAEwB,SAAS,GAAS,IAGlD,GAAI+B,EAAU5D,OAAST,EAAiB,CACtC,MAAMuB,EAAS,uBAAsBT,4BAA4CuD,EAAU5D,UAC3F4D,EAAYA,EAAUL,MAAM,EAAGhE,GAC/B0B,KAAKC,SAAS,CAAEJ,MAAAA,IAElB,MAAMf,EAA4B6D,EAAUxD,KAAKD,IAAD,CAAcE,KAAMF,MACpEc,KAAKmB,iBAAiB/B,EAAM,CAAEN,OAAAA,EAAQ8B,SAAS,IAC/C,MAAOf,GACPgD,QAAQhD,MAAMA,IAID,kBAACU,EAAkBiB,GAClC,MAAM,iBAAEO,GAAqB/B,KAAKK,MAC9BmB,GACFxB,KAAKmB,iBAAiBK,EAAc,CAAEZ,SAAS,GAAS,wBAAuBL,KAEjF,IACE,MAAMuC,QAAuBf,EAAiBgB,kBAAkBxC,GAAU,GAE1E,GAAIA,IAAa9B,EAAcuB,KAAKQ,MAAM9B,QAIxC,YAHI8C,GACFxB,KAAKmB,iBAAiBK,EAAc,CAAEZ,SAAS,KAInD,GAA2C,IAAvCoC,OAAOC,KAAKH,GAAgB/D,OAE9B,YADAiB,KAAKC,SAAS,CAAEJ,MAAQ,wCAAuCU,MAGjE,MAAM7B,EA9SL,SACLA,EACAoE,EACAtB,GAEA,OAAO9C,EAAOS,KAAKP,IACjB,MAAMsE,EAAiBJ,EAAelE,EAAMQ,MAC5C,GAAI8D,EAAgB,CAClB,IAAIC,EACJ,GAAIvE,EAAMQ,OAASoC,GAAgB5C,EAAME,OAEvCqE,EAAiBvE,EAAME,WAClB,OAEL,MAAME,EAA8B,IAAIoE,KACtC,UAAAxE,EAAME,cAAN,eAAcG,QAAQC,GAAUA,EAAML,WAAUM,KAAKD,GAAUA,EAAME,SAAS,IAGhF+D,EAAiBD,EAAe/D,KAAKD,IAAD,CAAcE,KAAMF,EAAOL,SAAUG,EAAeqE,IAAInE,OAE9F,wBAAYN,EAAZ,CAAmBgC,SAAS,EAAO9B,OAAQqE,EAAgBrC,OAAQqC,EAAepE,SAIpF,wBAAYH,EAAZ,CAAmBgC,SAAS,EAAOC,QAASqC,EAAgBpE,YAAQ6B,EAAWG,OAAQ,OAsRnDwC,CAAYtD,KAAKQ,MAAM9B,OAAQoE,EAAgBtB,GACjFxB,KAAKC,SAAS,CAAEvB,OAAAA,EAAQmB,MAAO,KAC3B2B,GACFxB,KAAKmB,iBAAiBK,EAAc,CAAEZ,SAAS,IAEjD,MAAOf,GACPgD,QAAQhD,MAAMA,IAII,uBAACU,GACrB,MAAM,iBAAEwB,GAAqB/B,KAAKK,MAClCL,KAAKC,SAAS,CAAEH,iBAAmB,uBAAsBS,IAAYV,MAAO,KAC5E,MAAM0D,QAAgBxB,EAAiBJ,YAAYpB,GACnDP,KAAKC,SAAS,CAAEH,iBAAmB,sBAAqByD,EAAQxE,0BAGlEyE,SACE,MAAM,MAAEC,GAAUzD,KAAKK,OACjB,OAAE3B,EAAF,WAAUiB,EAAV,OAAsBC,EAAtB,MAA8BC,EAA9B,iBAAqCC,GAAqBE,KAAKQ,MACrE,GAAsB,IAAlB9B,EAAOK,OACT,cAAO,SAAC,EAAA2E,mBAAD,CAAoBC,KAAK,uBAElC,MAAMC,EAzSSH,CAAAA,IAAD,CAChBI,QAASC,EAAAA,GAAI;wBACSL,EAAMM,OAAOC,WAAWC;eACjCR,EAAMS,QAAQ;;IAG3BC,KAAML,EAAAA,GAAI;kBACML,EAAMS,QAAQ;;;;;IAM9BE,QAASN,EAAAA,GAAI;;gBAECL,EAAMS,QAAQ,EAAG;;;IAI/B3D,SAAUuD,EAAAA,GAAI;mBACGL,EAAMY,WAAWC;qBACfb,EAAMS,QAAQ;IAEjCtE,OAAQkE,EAAAA,GAAI;eACCL,EAAMS,QAAQ;aAChBT,EAAMM,OAAOJ,KAAKM;;;;;;;;;;;IAY7BM,cAAeT,EAAAA,GAAI;;IAGnBjE,MAAOiE,EAAAA,GAAI;aACAL,EAAMM,OAAOlE,MAAM2E;IAE9BC,UAAWX,EAAAA,GAAI;oBACGL,EAAMS,QAAQ;IAEhCQ,iBAAkBZ,EAAAA,GAAI;6BACKL,EAAMM,OAAOY,OAAOC;cACnCnB,EAAMS,QAAQ,EAAG;eAChBT,EAAMS,QAAQ,EAAG,EAAG,EAAG;IAEpCW,cAAef,EAAAA,GAAI;;;kBAGHL,EAAMS,QAAQ;IAE9BY,WAAYhB,EAAAA,GAAI;oBACEL,EAAMS,QAAQ;qBACbT,EAAMS,QAAQ;IAEjCpE,iBAAkBgE,EAAAA,GAAI;eACTL,EAAMS,QAAQ;qBACRT,EAAMS,QAAQ;aACtBT,EAAMM,OAAOJ,KAAKoB;;;;MA0OZC,CAAUvB,GACnBlD,EAAW9B,EAAcuB,KAAKQ,MAAM9B,QACpCuG,EAAQ1E,IAAa/B,EAE3B,IAAIG,EAAiBD,EAAOO,QAAQL,GAAUA,EAAMC,UAAYD,EAAME,SAiCtE,OA/BEH,EADEgB,EACehB,EAAeQ,KAAKP,IACnC,MAAMsG,EAAgBtG,EAAME,OAAQG,QAAQC,IAE1C,GAAIA,EAAML,SAER,OADAK,EAAMiG,oBAAiBxE,GAChB,EAET,MAAMyE,GAAmBC,EAAAA,EAAAA,YAAWnG,EAAME,KAAKkG,cAAe3F,EAAW2F,eACzE,QAAIF,EAAiBG,QACnBrG,EAAMiG,eAAiBC,EAAiBI,OACxCtG,EAAMuG,MAAQL,EAAiBM,UACxB,MAKX,wBACK9G,EADL,CAEEE,QAAQ6G,EAAAA,EAAAA,QAAOT,GAAgBhG,GAAWA,EAAML,UAAY+G,EAAAA,EAAW1G,EAAMuG,aAKhEzF,KAAKQ,MAAM9B,OACzBO,QAAQL,GAAUA,EAAMC,UAAYD,EAAME,SAC1CK,KAAKP,GAAD,iBACAA,EADA,CAEHE,OAAQF,MAAAA,GAAAA,EAAOE,OAASF,EAAME,OAAOK,KAAKD,GAAD,iBAAiBA,EAAjB,CAAwBiG,oBAAgBxE,MAAgB,QAKrG,iBAAKkF,UAAWjC,EAAOC,QAAvB,WACE,iBAAKgC,UAAWjC,EAAOQ,QAAvB,iBACE,SAAC,EAAA0B,MAAD,CAAOC,YAAY,2DAAnB,6CAGA,gBAAKF,UAAWjC,EAAOO,KAAvB,SACGzF,EAAOS,KAAKP,IACX,SAAC,eAAD,CAEEQ,KAAMR,EAAMQ,KACZwB,QAAShC,EAAMgC,QACfoF,OAAQpH,EAAMC,SACdgC,OAAQjC,EAAMiC,OACdC,OAAQlC,EAAMkC,OACdmF,QAASjG,KAAKkG,cANTtH,EAAMQ,cAWnB,iBAAKyG,UAAWjC,EAAOQ,QAAvB,iBACE,SAAC,EAAA0B,MAAD,CAAOC,YAAY,gIAAnB,sDAGA,0BACE,SAAC,EAAAI,MAAD,CAAO1F,SAAUT,KAAKoG,eAAgB,aAAW,+BAA+BlH,MAAOS,OAEzF,gBAAKkG,UAAWjC,EAAOiB,cAAvB,SACGlG,EAAeQ,KAAKP,IAAD,eAClB,iBAAKyH,KAAK,OAAwBR,UAAWjC,EAAOc,iBAApD,WACE,gBAAKmB,UAAWjC,EAAOkB,WAAY,aAAa,cAAalG,EAAMQ,OAAnE,UACE,SAAC,eAAD,CACEA,KAAMR,EAAMQ,KACZwB,QAAShC,EAAMgC,QACfoF,OAAQpH,EAAMC,SACdgC,OAAQjC,EAAMiC,OAEdC,OAAQlC,EAAMkC,SAAN,UAAgBlC,EAAME,cAAtB,aAAgB,EAAcC,QACtCkH,QAASjG,KAAKkG,kBAGlB,SAAC,KAAD,CACEI,OAAQ,IACRC,WAAW,UAAA3H,EAAME,cAAN,eAAcC,SAAU,EACnCyH,SAAU,GACVC,QAAUlE,GAAO3D,EAAME,OAA6ByD,GAAGnD,KACvDsH,MAAO,IACPb,UAAWjC,EAAOa,UANpB,SAQG,IAAsB,UAArB,MAAEkC,EAAF,MAASC,GAAY,EACrB,MAAM1H,EAAK,UAAGN,EAAME,cAAT,aAAG,EAAe6H,GAC7B,OAAKzH,GAIH,gBAAK0H,MAAOA,EAAZ,UACE,SAAC,eAAD,CACExH,KAAMR,EAAMQ,KACZF,MAAOA,MAAAA,OAAF,EAAEA,EAAOE,KACd4G,OAAQ9G,MAAAA,OAAF,EAAEA,EAAOL,SACfsG,eAAgBjG,MAAAA,OAAF,EAAEA,EAAOiG,eACvBc,QAASjG,KAAK6G,aACdlH,WAAYA,MAVT,UAvBOf,EAAMQ,eA2ClC,iBAAKyG,UAAWjC,EAAOQ,QAAvB,iBACE,SAAC,EAAA0B,MAAD,sCACA,gBAAK,aAAW,WAAWD,UAAWjC,EAAOrD,SAA7C,SACGA,IAEFT,IAAoB,gBAAK+F,UAAWjC,EAAO9D,iBAAvB,SAA0CA,KAC/D,UAAC,EAAAgH,gBAAD,YACE,SAAC,EAAAC,OAAD,CAAQ,aAAW,8BAA8BC,SAAU/B,EAAOgB,QAASjG,KAAKiH,oBAAhF,wBAGA,SAAC,EAAAF,OAAD,CACE,aAAW,iCACXG,QAAQ,YACRF,SAAU/B,EACVgB,QAASjG,KAAKmH,uBAJhB,6BAQA,SAAC,EAAAJ,OAAD,CACE,aAAW,yBACXG,QAAQ,YACRF,SAAU/B,EACVgB,QAASjG,KAAKoH,gBAJhB,gCAQA,SAAC,EAAAL,OAAD,CAAQ,aAAW,wBAAwBG,QAAQ,YAAYjB,QAASjG,KAAKqH,aAA7E,oBAGA,gBAAKxB,WAAWyB,EAAAA,EAAAA,IAAG1D,EAAOhE,QAASA,GAAUC,IAAU+D,EAAOW,eAA9D,UACE,iBAAMsB,UAAWhG,EAAQ+D,EAAO/D,MAAQ,GAAxC,SAA6CA,GAASD,gBAS7D,MAAM2H,GAAmBC,EAAAA,EAAAA,YAAW/H,G,wHCrgB3C,SAASgI,EAAoBC,EAA7B,GAAgH,IAA/D,iBAAEC,EAAF,cAAoBC,GAA2C,EAE9G,OAAQD,GACN,IAAK,iBAAkB,CACrB,MAAME,EAAWC,EAAAA,QAAAA,mBACZD,GAAyB,MAAbA,GAAiC,MAAbA,IACnCH,GAAc,KAEhB,MAGF,IAAK,uBAAwB,CAE3B,IAAIK,EAAqB,GAEpBH,EAAcI,MAAM,iBACvBD,EAAqB,KAGvBA,IAAsBE,EAAAA,EAAAA,IAA2BP,EAAYE,GAE1B,MAA/BE,EAAAA,QAAAA,qBACFC,GAAsB,KAGxBL,EAAaK,EAEb,OAMJ,OAAOL,EAcF,MAAMQ,UAAuBxI,EAAAA,cAIlCyI,YAAY9H,GACV+H,MAAM/H,GADgC,8CAF3B,GAE2B,+BAyChBE,IACtBP,KAAKqI,cAAc9H,GAAU,GAC7BP,KAAKC,SAAS,CAAEqI,qBAAqB,OA3CC,wBA8CxB,CAACpJ,EAAeqJ,KAE9B,MAAM,MAAE7H,EAAF,SAASD,EAAT,WAAmB+H,GAAexI,KAAKK,MAC7C,GAAII,EAAU,CAEZA,EADkB,OAAH,UAAQC,EAAR,CAAe+H,KAAMvJ,KAGhCqJ,GAAYC,GACdA,QAtDkC,+BA2DjB,KAChBxI,KAAKQ,MAAM8H,qBAKdnI,EAAAA,EAAAA,mBAAkB,kCAAmC,CACnDC,IAAKJ,KAAKK,MAAMD,IAChBE,UAAW,sBANbH,EAAAA,EAAAA,mBAAkB,kCAAmC,CACnDC,IAAKJ,KAAKK,MAAMD,MAQpBJ,KAAKC,UAAUO,IAAD,CAAc8H,qBAAsB9H,EAAM8H,2BAtElB,sBAyE1BI,MAAAA,IACZ,MAAM,WAAEC,GAAe3I,KAAKK,MAE5B,IAAKsI,EAAW5G,iBACd,MAAO,CAAE6G,YAAa,IAGxB,MAAMC,EAAuBF,EAAW5G,kBAClC,QAAE+G,GAAY9I,KAAKK,OACnB,OAAE0I,EAAF,KAAUpF,EAAV,MAAgBzE,EAAhB,eAAuB8J,EAAvB,SAAuCC,GAAaC,EAM1D,aAJqBL,EAAqBM,uBACxC,CAAExF,KAAAA,EAAMzE,MAAAA,EAAO6J,OAAAA,EAAQC,eAAAA,EAAgBC,SAAAA,GACvC,CAAEH,QAAAA,OAnFJ9I,KAAKQ,MAAQ,CAAE4I,cAAc,EAAOd,qBAAqB,GAEzDtI,KAAKqJ,QAAU,EACbC,EAAAA,EAAAA,iBACAC,EAAAA,EAAAA,YACE,CACEC,OAASC,GAA+B,UAAhBA,EAAKC,QAAoC,eAAdD,EAAKE,KACxDC,UAAYH,GAAe,SAHrB,iBAKFI,EAAAA,UALE,CAK8BC,MAAO9J,KAAKK,MAAMsI,WAAW5G,iBAAiB6H,gBAKnE,0BACrB5J,KAAK+J,YAAa,QACZ/J,KAAKK,MAAMsI,WAAW5G,iBAAiBG,QACzClC,KAAK+J,YACP/J,KAAKC,SAAS,CAAEmJ,cAAc,IAIlCY,uBACEhK,KAAK+J,YAAa,EAGpBE,mBAAmBC,GACjB,MAAM,MACJC,EACAxB,YAAY,iBAAE5G,IACZ/B,KAAKK,OACa+J,EAAAA,EAAAA,IAAoBD,EAAOD,EAAUC,QAGzDpI,EAAiBsI,cAsDrB7G,SACE,MAAM,kBACJ8G,EADI,MAEJ5J,EAFI,IAGJN,EAHI,WAIJuI,EAJI,YAKJ4B,EAAc,6CACZvK,KAAKK,OAEH,aAAE+I,EAAF,oBAAgBd,GAAwBtI,KAAKQ,MAC7CqI,EAAuBF,EAAW5G,iBAClCyI,EAAY7B,EAAW5G,iBAAmB8G,EAAqB2B,eAAY7J,EAC3E8J,EAAe5B,EAAqBxG,eAAetD,OAAS,EAC5D2L,EArKV,SAAwBC,EAAoBF,GAC1C,OAAKE,EAGAF,EAGE,cAFE,kBAHA,oBAmKaG,CAAexB,EAAcqB,GAC3CI,IAAmBzB,GAAgBqB,GAEzC,OACE,SAACK,EAAA,EAAD,CAAqCC,WA3Kd,0CA2KgDC,aAAc,GAArF,SACG,CAAC/I,EAAgBgJ,EAAsBC,KAEpC,iCACE,iBACErF,UAAU,iEACV,cAAa7F,KAAKK,MAAM,eAF1B,WAIE,oBACEwF,UAAU,sCACVI,QAASjG,KAAKmL,qBACdnE,SAAU6D,EAHZ,UAKGH,GACD,SAAC,EAAAU,KAAD,CAAMhM,KAAMkJ,EAAsB,aAAe,oBAEnD,gBAAKzC,UAAU,mDAAf,UACE,SAAC,EAAAwF,WAAD,CACEC,kBAAmBtL,KAAKqJ,QACxBmB,UAAWA,EACX9J,MAAOA,EAAM+H,KACb8C,YAAavL,KAAKuL,YAClBC,sBAAuB/D,EACvBhH,SAAUT,KAAKqI,cACfoD,OAAQzL,KAAKK,MAAMoL,OACnBjD,WAAYxI,KAAKK,MAAMmI,WACvB+B,YAAaA,EACbmB,aAAa,cAIlBpD,IACC,gBAAKzC,UAAU,UAAf,UACE,SAAC0B,EAAD,CACExF,iBAAkB8G,EAClBpI,SAAUT,KAAK2L,qBACf1J,eAAgBA,GAAkB,GAClCS,oBAAqBuI,EACrBlK,qBAAsBmK,EACtB9K,IAAKA,MAKVkK,U,eC9Of,SAASsB,EAAaC,GACpB,OAGqBC,EAHAD,EAAe,IAI7BE,KAAKC,MAAMF,EAAU,IAD9B,IAAuBA,EAIhB,SAAS1B,EAAoBD,EAAmB8B,GACrD,GAAI9B,GAAS8B,EAAW,CACtB,MAAMC,EAAiBN,EAAazB,EAAMgC,KAAKC,aAAeR,EAAaK,EAAUE,KAAKC,WACpFC,EAAeT,EAAazB,EAAMmC,GAAGF,aAAeR,EAAaK,EAAUK,GAAGF,WAEpF,QAASF,GAAkBG,GAE7B,OAAO,E,6CAOT,MAAME,EAAqB,uBASpB,SAAS/M,EAAgCgN,GAC9C,OAAOA,EAAWC,QAAQ,MAAO,QAAQA,QAAQ,MAAO,OAAOA,QAAQ,KAAM,OAGxE,SAASnN,EAAgCkN,GAC9C,OAAOhN,EAAiDgN,EAZ3CC,QAAQF,EAAoB,SAepC,SAAStE,EAA2BuE,EAAoBjM,GAC7D,OAKK,SAAyBA,GAC9B,GAAIA,IAAaA,EAASkC,SAAS,OAASlC,EAASkC,SAAS,OAC5D,OAAO,EAET,OAAO,EATAiK,CAAgBnM,GACnBjB,EAAgCkN,GAChChN,EAAgCgN","sources":["webpack://grafana/./public/app/plugins/datasource/loki/components/LokiLabelBrowser.tsx","webpack://grafana/./public/app/plugins/datasource/loki/components/LokiQueryField.tsx","webpack://grafana/./public/app/plugins/datasource/loki/language_utils.ts"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { sortBy } from 'lodash';\nimport React, { ChangeEvent } from 'react';\nimport { FixedSizeList } from 'react-window';\n\nimport { CoreApp, GrafanaTheme2 } from '@grafana/data';\nimport { reportInteraction } from '@grafana/runtime';\nimport {\n Button,\n HighlightPart,\n HorizontalGroup,\n Input,\n Label,\n LoadingPlaceholder,\n withTheme2,\n BrowserLabel as LokiLabel,\n fuzzyMatch,\n} from '@grafana/ui';\n\nimport PromQlLanguageProvider from '../../prometheus/language_provider';\nimport LokiLanguageProvider from '../language_provider';\nimport { escapeLabelValueInExactSelector, escapeLabelValueInRegexSelector } from '../language_utils';\n\n// Hard limit on labels to render\nconst MAX_LABEL_COUNT = 1000;\nconst MAX_VALUE_COUNT = 10000;\nconst MAX_AUTO_SELECT = 4;\nconst EMPTY_SELECTOR = '{}';\n\nexport interface BrowserProps {\n // TODO #33976: Is it possible to use a common interface here? For example: LabelsLanguageProvider\n languageProvider: LokiLanguageProvider | PromQlLanguageProvider;\n onChange: (selector: string) => void;\n theme: GrafanaTheme2;\n app?: CoreApp;\n autoSelect?: number;\n hide?: () => void;\n lastUsedLabels: string[];\n storeLastUsedLabels: (labels: string[]) => void;\n deleteLastUsedLabels: () => void;\n}\n\ninterface BrowserState {\n labels: SelectableLabel[];\n searchTerm: string;\n status: string;\n error: string;\n validationStatus: string;\n}\n\ninterface FacettableValue {\n name: string;\n selected?: boolean;\n highlightParts?: HighlightPart[];\n order?: number;\n}\n\nexport interface SelectableLabel {\n name: string;\n selected?: boolean;\n loading?: boolean;\n values?: FacettableValue[];\n hidden?: boolean;\n facets?: number;\n}\n\nexport function buildSelector(labels: SelectableLabel[]): string {\n const selectedLabels = [];\n for (const label of labels) {\n if (label.selected && label.values && label.values.length > 0) {\n const selectedValues = label.values.filter((value) => value.selected).map((value) => value.name);\n if (selectedValues.length > 1) {\n selectedLabels.push(`${label.name}=~\"${selectedValues.map(escapeLabelValueInRegexSelector).join('|')}\"`);\n } else if (selectedValues.length === 1) {\n selectedLabels.push(`${label.name}=\"${escapeLabelValueInExactSelector(selectedValues[0])}\"`);\n }\n }\n }\n return ['{', selectedLabels.join(','), '}'].join('');\n}\n\nexport function facetLabels(\n labels: SelectableLabel[],\n possibleLabels: Record<string, string[]>,\n lastFacetted?: string\n): SelectableLabel[] {\n return labels.map((label) => {\n const possibleValues = possibleLabels[label.name];\n if (possibleValues) {\n let existingValues: FacettableValue[];\n if (label.name === lastFacetted && label.values) {\n // Facetting this label, show all values\n existingValues = label.values;\n } else {\n // Keep selection in other facets\n const selectedValues: Set<string> = new Set(\n label.values?.filter((value) => value.selected).map((value) => value.name) || []\n );\n // Values for this label have not been requested yet, let's use the facetted ones as the initial values\n existingValues = possibleValues.map((value) => ({ name: value, selected: selectedValues.has(value) }));\n }\n return { ...label, loading: false, values: existingValues, facets: existingValues.length };\n }\n\n // Label is facetted out, hide all values\n return { ...label, loading: false, hidden: !possibleValues, values: undefined, facets: 0 };\n });\n}\n\nconst getStyles = (theme: GrafanaTheme2) => ({\n wrapper: css`\n background-color: ${theme.colors.background.secondary};\n padding: ${theme.spacing(2)};\n width: 100%;\n `,\n list: css`\n margin-top: ${theme.spacing(1)};\n display: flex;\n flex-wrap: wrap;\n max-height: 200px;\n overflow: auto;\n `,\n section: css`\n & + & {\n margin: ${theme.spacing(2, 0)};\n }\n position: relative;\n `,\n selector: css`\n font-family: ${theme.typography.fontFamilyMonospace};\n margin-bottom: ${theme.spacing(1)};\n `,\n status: css`\n padding: ${theme.spacing(0.5)};\n color: ${theme.colors.text.secondary};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n /* using absolute positioning because flex interferes with ellipsis */\n position: absolute;\n width: 50%;\n right: 0;\n text-align: right;\n transition: opacity 100ms linear;\n opacity: 0;\n `,\n statusShowing: css`\n opacity: 1;\n `,\n error: css`\n color: ${theme.colors.error.main};\n `,\n valueList: css`\n margin-right: ${theme.spacing(1)};\n `,\n valueListWrapper: css`\n border-left: 1px solid ${theme.colors.border.medium};\n margin: ${theme.spacing(1, 0)};\n padding: ${theme.spacing(1, 0, 1, 1)};\n `,\n valueListArea: css`\n display: flex;\n flex-wrap: wrap;\n margin-top: ${theme.spacing(1)};\n `,\n valueTitle: css`\n margin-left: -${theme.spacing(0.5)};\n margin-bottom: ${theme.spacing(1)};\n `,\n validationStatus: css`\n padding: ${theme.spacing(0.5)};\n margin-bottom: ${theme.spacing(1)};\n color: ${theme.colors.text.maxContrast};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n `,\n});\n\nexport class UnthemedLokiLabelBrowser extends React.Component<BrowserProps, BrowserState> {\n state: BrowserState = {\n labels: [] as SelectableLabel[],\n searchTerm: '',\n status: 'Ready',\n error: '',\n validationStatus: '',\n };\n\n onChangeSearch = (event: ChangeEvent<HTMLInputElement>) => {\n this.setState({ searchTerm: event.target.value });\n };\n\n onClickRunLogsQuery = () => {\n reportInteraction('grafana_loki_log_browser_closed', {\n app: this.props.app,\n closeType: 'showLogsButton',\n });\n const selector = buildSelector(this.state.labels);\n this.props.onChange(selector);\n };\n\n onClickRunMetricsQuery = () => {\n reportInteraction('grafana_loki_log_browser_closed', {\n app: this.props.app,\n closeType: 'showLogsRateButton',\n });\n const selector = buildSelector(this.state.labels);\n const query = `rate(${selector}[$__interval])`;\n this.props.onChange(query);\n };\n\n onClickClear = () => {\n reportInteraction('grafana_loki_log_browser_closed', {\n app: this.props.app,\n closeType: 'clearButton',\n });\n this.setState((state) => {\n const labels: SelectableLabel[] = state.labels.map((label) => ({\n ...label,\n values: undefined,\n selected: false,\n loading: false,\n hidden: false,\n facets: undefined,\n }));\n return { labels, searchTerm: '', status: '', error: '', validationStatus: '' };\n });\n this.props.deleteLastUsedLabels();\n };\n\n onClickLabel = (name: string, value: string | undefined, event: React.MouseEvent<HTMLElement>) => {\n const label = this.state.labels.find((l) => l.name === name);\n if (!label) {\n return;\n }\n // Toggle selected state\n const selected = !label.selected;\n let nextValue: Partial<SelectableLabel> = { selected };\n if (label.values && !selected) {\n // Deselect all values if label was deselected\n const values = label.values.map((value) => ({ ...value, selected: false }));\n nextValue = { ...nextValue, facets: 0, values };\n }\n // Resetting search to prevent empty results\n this.setState({ searchTerm: '' });\n this.updateLabelState(name, nextValue, '', () => this.doFacettingForLabel(name));\n };\n\n onClickValue = (name: string, value: string | undefined, event: React.MouseEvent<HTMLElement>) => {\n const label = this.state.labels.find((l) => l.name === name);\n if (!label || !label.values) {\n return;\n }\n // Resetting search to prevent empty results\n this.setState({ searchTerm: '' });\n // Toggling value for selected label, leaving other values intact\n const values = label.values.map((v) => ({ ...v, selected: v.name === value ? !v.selected : v.selected }));\n this.updateLabelState(name, { values }, '', () => this.doFacetting(name));\n };\n\n onClickValidate = () => {\n const selector = buildSelector(this.state.labels);\n this.validateSelector(selector);\n };\n\n updateLabelState(name: string, updatedFields: Partial<SelectableLabel>, status = '', cb?: () => void) {\n this.setState((state) => {\n const labels: SelectableLabel[] = state.labels.map((label) => {\n if (label.name === name) {\n return { ...label, ...updatedFields };\n }\n return label;\n });\n // New status overrides errors\n const error = status ? '' : state.error;\n return { labels, status, error, validationStatus: '' };\n }, cb);\n }\n\n componentDidMount() {\n const { languageProvider, autoSelect = MAX_AUTO_SELECT, lastUsedLabels } = this.props;\n if (languageProvider) {\n const selectedLabels: string[] = lastUsedLabels;\n languageProvider.start().then(() => {\n let rawLabels: string[] = languageProvider.getLabelKeys();\n if (rawLabels.length > MAX_LABEL_COUNT) {\n const error = `Too many labels found (showing only ${MAX_LABEL_COUNT} of ${rawLabels.length})`;\n rawLabels = rawLabels.slice(0, MAX_LABEL_COUNT);\n this.setState({ error });\n }\n // Auto-select all labels if label list is small enough\n const labels: SelectableLabel[] = rawLabels.map((label, i, arr) => ({\n name: label,\n selected: (arr.length <= autoSelect && selectedLabels.length === 0) || selectedLabels.includes(label),\n loading: false,\n }));\n // Pre-fetch values for selected labels\n this.setState({ labels }, () => {\n this.state.labels.forEach((label) => {\n if (label.selected) {\n this.fetchValues(label.name, EMPTY_SELECTOR);\n }\n });\n });\n });\n }\n }\n\n doFacettingForLabel(name: string) {\n const label = this.state.labels.find((l) => l.name === name);\n if (!label) {\n return;\n }\n const selectedLabels = this.state.labels.filter((label) => label.selected).map((label) => label.name);\n this.props.storeLastUsedLabels(selectedLabels);\n if (label.selected) {\n // Refetch values for newly selected label...\n if (!label.values) {\n this.fetchValues(name, buildSelector(this.state.labels));\n }\n } else {\n // Only need to facet when deselecting labels\n this.doFacetting();\n }\n }\n\n doFacetting = (lastFacetted?: string) => {\n const selector = buildSelector(this.state.labels);\n if (selector === EMPTY_SELECTOR) {\n // Clear up facetting\n const labels: SelectableLabel[] = this.state.labels.map((label) => {\n return { ...label, facets: 0, values: undefined, hidden: false };\n });\n this.setState({ labels }, () => {\n // Get fresh set of values\n this.state.labels.forEach((label) => label.selected && this.fetchValues(label.name, selector));\n });\n } else {\n // Do facetting\n this.fetchSeries(selector, lastFacetted);\n }\n };\n\n async fetchValues(name: string, selector: string) {\n const { languageProvider } = this.props;\n this.updateLabelState(name, { loading: true }, `Fetching values for ${name}`);\n try {\n let rawValues = await languageProvider.getLabelValues(name);\n // If selector changed, clear loading state and discard result by returning early\n if (selector !== buildSelector(this.state.labels)) {\n this.updateLabelState(name, { loading: false }, '');\n return;\n }\n if (rawValues.length > MAX_VALUE_COUNT) {\n const error = `Too many values for ${name} (showing only ${MAX_VALUE_COUNT} of ${rawValues.length})`;\n rawValues = rawValues.slice(0, MAX_VALUE_COUNT);\n this.setState({ error });\n }\n const values: FacettableValue[] = rawValues.map((value) => ({ name: value }));\n this.updateLabelState(name, { values, loading: false });\n } catch (error) {\n console.error(error);\n }\n }\n\n async fetchSeries(selector: string, lastFacetted?: string) {\n const { languageProvider } = this.props;\n if (lastFacetted) {\n this.updateLabelState(lastFacetted, { loading: true }, `Facetting labels for ${selector}`);\n }\n try {\n const possibleLabels = await languageProvider.fetchSeriesLabels(selector, true);\n // If selector changed, clear loading state and discard result by returning early\n if (selector !== buildSelector(this.state.labels)) {\n if (lastFacetted) {\n this.updateLabelState(lastFacetted, { loading: false });\n }\n return;\n }\n if (Object.keys(possibleLabels).length === 0) {\n this.setState({ error: `Empty results, no matching label for ${selector}` });\n return;\n }\n const labels: SelectableLabel[] = facetLabels(this.state.labels, possibleLabels, lastFacetted);\n this.setState({ labels, error: '' });\n if (lastFacetted) {\n this.updateLabelState(lastFacetted, { loading: false });\n }\n } catch (error) {\n console.error(error);\n }\n }\n\n async validateSelector(selector: string) {\n const { languageProvider } = this.props;\n this.setState({ validationStatus: `Validating selector ${selector}`, error: '' });\n const streams = await languageProvider.fetchSeries(selector);\n this.setState({ validationStatus: `Selector is valid (${streams.length} streams found)` });\n }\n\n render() {\n const { theme } = this.props;\n const { labels, searchTerm, status, error, validationStatus } = this.state;\n if (labels.length === 0) {\n return <LoadingPlaceholder text=\"Loading labels...\" />;\n }\n const styles = getStyles(theme);\n const selector = buildSelector(this.state.labels);\n const empty = selector === EMPTY_SELECTOR;\n\n let selectedLabels = labels.filter((label) => label.selected && label.values);\n if (searchTerm) {\n selectedLabels = selectedLabels.map((label) => {\n const searchResults = label.values!.filter((value) => {\n // Always return selected values\n if (value.selected) {\n value.highlightParts = undefined;\n return true;\n }\n const fuzzyMatchResult = fuzzyMatch(value.name.toLowerCase(), searchTerm.toLowerCase());\n if (fuzzyMatchResult.found) {\n value.highlightParts = fuzzyMatchResult.ranges;\n value.order = fuzzyMatchResult.distance;\n return true;\n } else {\n return false;\n }\n });\n return {\n ...label,\n values: sortBy(searchResults, (value) => (value.selected ? -Infinity : value.order)),\n };\n });\n } else {\n // Clear highlight parts when searchTerm is cleared\n selectedLabels = this.state.labels\n .filter((label) => label.selected && label.values)\n .map((label) => ({\n ...label,\n values: label?.values ? label.values.map((value) => ({ ...value, highlightParts: undefined })) : [],\n }));\n }\n\n return (\n <div className={styles.wrapper}>\n <div className={styles.section}>\n <Label description=\"Which labels would you like to consider for your search?\">\n 1. Select labels to search in\n </Label>\n <div className={styles.list}>\n {labels.map((label) => (\n <LokiLabel\n key={label.name}\n name={label.name}\n loading={label.loading}\n active={label.selected}\n hidden={label.hidden}\n facets={label.facets}\n onClick={this.onClickLabel}\n />\n ))}\n </div>\n </div>\n <div className={styles.section}>\n <Label description=\"Choose the label values that you would like to use for the query. Use the search field to find values across selected labels.\">\n 2. Find values for the selected labels\n </Label>\n <div>\n <Input onChange={this.onChangeSearch} aria-label=\"Filter expression for values\" value={searchTerm} />\n </div>\n <div className={styles.valueListArea}>\n {selectedLabels.map((label) => (\n <div role=\"list\" key={label.name} className={styles.valueListWrapper}>\n <div className={styles.valueTitle} aria-label={`Values for ${label.name}`}>\n <LokiLabel\n name={label.name}\n loading={label.loading}\n active={label.selected}\n hidden={label.hidden}\n //If no facets, we want to show number of all label values\n facets={label.facets || label.values?.length}\n onClick={this.onClickLabel}\n />\n </div>\n <FixedSizeList\n height={200}\n itemCount={label.values?.length || 0}\n itemSize={28}\n itemKey={(i) => (label.values as FacettableValue[])[i].name}\n width={200}\n className={styles.valueList}\n >\n {({ index, style }) => {\n const value = label.values?.[index];\n if (!value) {\n return null;\n }\n return (\n <div style={style}>\n <LokiLabel\n name={label.name}\n value={value?.name}\n active={value?.selected}\n highlightParts={value?.highlightParts}\n onClick={this.onClickValue}\n searchTerm={searchTerm}\n />\n </div>\n );\n }}\n </FixedSizeList>\n </div>\n ))}\n </div>\n </div>\n <div className={styles.section}>\n <Label>3. Resulting selector</Label>\n <div aria-label=\"selector\" className={styles.selector}>\n {selector}\n </div>\n {validationStatus && <div className={styles.validationStatus}>{validationStatus}</div>}\n <HorizontalGroup>\n <Button aria-label=\"Use selector as logs button\" disabled={empty} onClick={this.onClickRunLogsQuery}>\n Show logs\n </Button>\n <Button\n aria-label=\"Use selector as metrics button\"\n variant=\"secondary\"\n disabled={empty}\n onClick={this.onClickRunMetricsQuery}\n >\n Show logs rate\n </Button>\n <Button\n aria-label=\"Validate submit button\"\n variant=\"secondary\"\n disabled={empty}\n onClick={this.onClickValidate}\n >\n Validate selector\n </Button>\n <Button aria-label=\"Selector clear button\" variant=\"secondary\" onClick={this.onClickClear}>\n Clear\n </Button>\n <div className={cx(styles.status, (status || error) && styles.statusShowing)}>\n <span className={error ? styles.error : ''}>{error || status}</span>\n </div>\n </HorizontalGroup>\n </div>\n </div>\n );\n }\n}\n\nexport const LokiLabelBrowser = withTheme2(UnthemedLokiLabelBrowser);\n","import { LanguageMap, languages as prismLanguages } from 'prismjs';\nimport React, { ReactNode } from 'react';\nimport { Plugin, Node } from 'slate';\n\nimport { QueryEditorProps } from '@grafana/data';\nimport { reportInteraction } from '@grafana/runtime';\nimport {\n SlatePrism,\n TypeaheadOutput,\n SuggestionsState,\n QueryField,\n TypeaheadInput,\n BracesPlugin,\n DOMUtil,\n Icon,\n} from '@grafana/ui';\nimport { LocalStorageValueProvider } from 'app/core/components/LocalStorageValueProvider';\n\nimport { LokiDatasource } from '../datasource';\nimport LokiLanguageProvider from '../language_provider';\nimport { escapeLabelValueInSelector, shouldRefreshLabels } from '../language_utils';\nimport { LokiQuery, LokiOptions } from '../types';\n\nimport { LokiLabelBrowser } from './LokiLabelBrowser';\n\nconst LAST_USED_LABELS_KEY = 'grafana.datasources.loki.browser.labels';\n\nfunction getChooserText(hasSyntax: boolean, hasLogLabels: boolean) {\n if (!hasSyntax) {\n return 'Loading labels...';\n }\n if (!hasLogLabels) {\n return '(No logs found)';\n }\n return 'Log browser';\n}\n\nfunction willApplySuggestion(suggestion: string, { typeaheadContext, typeaheadText }: SuggestionsState): string {\n // Modify suggestion based on context\n switch (typeaheadContext) {\n case 'context-labels': {\n const nextChar = DOMUtil.getNextCharacter();\n if (!nextChar || nextChar === '}' || nextChar === ',') {\n suggestion += '=';\n }\n break;\n }\n\n case 'context-label-values': {\n // Always add quotes and remove existing ones instead\n let suggestionModified = '';\n\n if (!typeaheadText.match(/^(!?=~?\"|\")/)) {\n suggestionModified = '\"';\n }\n\n suggestionModified += escapeLabelValueInSelector(suggestion, typeaheadText);\n\n if (DOMUtil.getNextCharacter() !== '\"') {\n suggestionModified += '\"';\n }\n\n suggestion = suggestionModified;\n\n break;\n }\n\n default:\n }\n\n return suggestion;\n}\n\nexport interface LokiQueryFieldProps extends QueryEditorProps<LokiDatasource, LokiQuery, LokiOptions> {\n ExtraFieldElement?: ReactNode;\n placeholder?: string;\n 'data-testid'?: string;\n}\n\ninterface LokiQueryFieldState {\n labelsLoaded: boolean;\n labelBrowserVisible: boolean;\n}\n\nexport class LokiQueryField extends React.PureComponent<LokiQueryFieldProps, LokiQueryFieldState> {\n plugins: Plugin[];\n _isMounted = false;\n\n constructor(props: LokiQueryFieldProps) {\n super(props);\n\n this.state = { labelsLoaded: false, labelBrowserVisible: false };\n\n this.plugins = [\n BracesPlugin(),\n SlatePrism(\n {\n onlyIn: (node: Node) => node.object === 'block' && node.type === 'code_block',\n getSyntax: (node: Node) => 'logql',\n },\n { ...(prismLanguages as LanguageMap), logql: this.props.datasource.languageProvider.getSyntax() }\n ),\n ];\n }\n\n async componentDidMount() {\n this._isMounted = true;\n await this.props.datasource.languageProvider.start();\n if (this._isMounted) {\n this.setState({ labelsLoaded: true });\n }\n }\n\n componentWillUnmount() {\n this._isMounted = false;\n }\n\n componentDidUpdate(prevProps: LokiQueryFieldProps) {\n const {\n range,\n datasource: { languageProvider },\n } = this.props;\n const refreshLabels = shouldRefreshLabels(range, prevProps.range);\n // We want to refresh labels when range changes (we round up intervals to a minute)\n if (refreshLabels) {\n languageProvider.fetchLabels();\n }\n }\n\n onChangeLabelBrowser = (selector: string) => {\n this.onChangeQuery(selector, true);\n this.setState({ labelBrowserVisible: false });\n };\n\n onChangeQuery = (value: string, override?: boolean) => {\n // Send text change to parent\n const { query, onChange, onRunQuery } = this.props;\n if (onChange) {\n const nextQuery = { ...query, expr: value };\n onChange(nextQuery);\n\n if (override && onRunQuery) {\n onRunQuery();\n }\n }\n };\n\n onClickChooserButton = () => {\n if (!this.state.labelBrowserVisible) {\n reportInteraction('grafana_loki_log_browser_opened', {\n app: this.props.app,\n });\n } else {\n reportInteraction('grafana_loki_log_browser_closed', {\n app: this.props.app,\n closeType: 'logBrowserButton',\n });\n }\n this.setState((state) => ({ labelBrowserVisible: !state.labelBrowserVisible }));\n };\n\n onTypeahead = async (typeahead: TypeaheadInput): Promise<TypeaheadOutput> => {\n const { datasource } = this.props;\n\n if (!datasource.languageProvider) {\n return { suggestions: [] };\n }\n\n const lokiLanguageProvider = datasource.languageProvider as LokiLanguageProvider;\n const { history } = this.props;\n const { prefix, text, value, wrapperClasses, labelKey } = typeahead;\n\n const result = await lokiLanguageProvider.provideCompletionItems(\n { text, value, prefix, wrapperClasses, labelKey },\n { history }\n );\n return result;\n };\n\n render() {\n const {\n ExtraFieldElement,\n query,\n app,\n datasource,\n placeholder = 'Enter a Loki query (run with Shift+Enter)',\n } = this.props;\n\n const { labelsLoaded, labelBrowserVisible } = this.state;\n const lokiLanguageProvider = datasource.languageProvider as LokiLanguageProvider;\n const cleanText = datasource.languageProvider ? lokiLanguageProvider.cleanText : undefined;\n const hasLogLabels = lokiLanguageProvider.getLabelKeys().length > 0;\n const chooserText = getChooserText(labelsLoaded, hasLogLabels);\n const buttonDisabled = !(labelsLoaded && hasLogLabels);\n\n return (\n <LocalStorageValueProvider<string[]> storageKey={LAST_USED_LABELS_KEY} defaultValue={[]}>\n {(lastUsedLabels, onLastUsedLabelsSave, onLastUsedLabelsDelete) => {\n return (\n <>\n <div\n className=\"gf-form-inline gf-form-inline--xs-view-flex-column flex-grow-1\"\n data-testid={this.props['data-testid']}\n >\n <button\n className=\"gf-form-label query-keyword pointer\"\n onClick={this.onClickChooserButton}\n disabled={buttonDisabled}\n >\n {chooserText}\n <Icon name={labelBrowserVisible ? 'angle-down' : 'angle-right'} />\n </button>\n <div className=\"gf-form gf-form--grow flex-shrink-1 min-width-15\">\n <QueryField\n additionalPlugins={this.plugins}\n cleanText={cleanText}\n query={query.expr}\n onTypeahead={this.onTypeahead}\n onWillApplySuggestion={willApplySuggestion}\n onChange={this.onChangeQuery}\n onBlur={this.props.onBlur}\n onRunQuery={this.props.onRunQuery}\n placeholder={placeholder}\n portalOrigin=\"loki\"\n />\n </div>\n </div>\n {labelBrowserVisible && (\n <div className=\"gf-form\">\n <LokiLabelBrowser\n languageProvider={lokiLanguageProvider}\n onChange={this.onChangeLabelBrowser}\n lastUsedLabels={lastUsedLabels || []}\n storeLastUsedLabels={onLastUsedLabelsSave}\n deleteLastUsedLabels={onLastUsedLabelsDelete}\n app={app}\n />\n </div>\n )}\n\n {ExtraFieldElement}\n </>\n );\n }}\n </LocalStorageValueProvider>\n );\n }\n}\n","import { TimeRange } from '@grafana/data';\n\nfunction roundMsToMin(milliseconds: number): number {\n return roundSecToMin(milliseconds / 1000);\n}\n\nfunction roundSecToMin(seconds: number): number {\n return Math.floor(seconds / 60);\n}\n\nexport function shouldRefreshLabels(range?: TimeRange, prevRange?: TimeRange): boolean {\n if (range && prevRange) {\n const sameMinuteFrom = roundMsToMin(range.from.valueOf()) === roundMsToMin(prevRange.from.valueOf());\n const sameMinuteTo = roundMsToMin(range.to.valueOf()) === roundMsToMin(prevRange.to.valueOf());\n // If both are same, don't need to refresh\n return !(sameMinuteFrom && sameMinuteTo);\n }\n return false;\n}\n\n// Loki regular-expressions use the RE2 syntax (https://github.com/google/re2/wiki/Syntax),\n// so every character that matches something in that list has to be escaped.\n// the list of meta characters is: *+?()|\\.[]{}^$\n// we make a javascript regular expression that matches those characters:\nconst RE2_METACHARACTERS = /[*+?()|\\\\.\\[\\]{}^$]/g;\nfunction escapeLokiRegexp(value: string): string {\n return value.replace(RE2_METACHARACTERS, '\\\\$&');\n}\n\n// based on the openmetrics-documentation, the 3 symbols we have to handle are:\n// - \\n ... the newline character\n// - \\ ... the backslash character\n// - \" ... the double-quote character\nexport function escapeLabelValueInExactSelector(labelValue: string): string {\n return labelValue.replace(/\\\\/g, '\\\\\\\\').replace(/\\n/g, '\\\\n').replace(/\"/g, '\\\\\"');\n}\n\nexport function escapeLabelValueInRegexSelector(labelValue: string): string {\n return escapeLabelValueInExactSelector(escapeLokiRegexp(labelValue));\n}\n\nexport function escapeLabelValueInSelector(labelValue: string, selector?: string): string {\n return isRegexSelector(selector)\n ? escapeLabelValueInRegexSelector(labelValue)\n : escapeLabelValueInExactSelector(labelValue);\n}\n\nexport function isRegexSelector(selector?: string) {\n if (selector && (selector.includes('=~') || selector.includes('!~'))) {\n return true;\n }\n return false;\n}\n"],"names":["MAX_LABEL_COUNT","MAX_VALUE_COUNT","MAX_AUTO_SELECT","EMPTY_SELECTOR","buildSelector","labels","selectedLabels","label","selected","values","length","selectedValues","filter","value","map","name","push","escapeLabelValueInRegexSelector","join","escapeLabelValueInExactSelector","UnthemedLokiLabelBrowser","React","searchTerm","status","error","validationStatus","event","this","setState","target","reportInteraction","app","props","closeType","selector","state","onChange","query","undefined","loading","hidden","facets","deleteLastUsedLabels","find","l","nextValue","updateLabelState","doFacettingForLabel","v","doFacetting","validateSelector","lastFacetted","forEach","fetchValues","fetchSeries","updatedFields","cb","componentDidMount","languageProvider","autoSelect","lastUsedLabels","start","then","rawLabels","getLabelKeys","slice","i","arr","includes","storeLastUsedLabels","rawValues","getLabelValues","console","possibleLabels","fetchSeriesLabels","Object","keys","possibleValues","existingValues","Set","has","facetLabels","streams","render","theme","LoadingPlaceholder","text","styles","wrapper","css","colors","background","secondary","spacing","list","section","typography","fontFamilyMonospace","statusShowing","main","valueList","valueListWrapper","border","medium","valueListArea","valueTitle","maxContrast","getStyles","empty","searchResults","highlightParts","fuzzyMatchResult","fuzzyMatch","toLowerCase","found","ranges","order","distance","sortBy","Infinity","className","Label","description","active","onClick","onClickLabel","Input","onChangeSearch","role","height","itemCount","itemSize","itemKey","width","index","style","onClickValue","HorizontalGroup","Button","disabled","onClickRunLogsQuery","variant","onClickRunMetricsQuery","onClickValidate","onClickClear","cx","LokiLabelBrowser","withTheme2","willApplySuggestion","suggestion","typeaheadContext","typeaheadText","nextChar","DOMUtil","suggestionModified","match","escapeLabelValueInSelector","LokiQueryField","constructor","super","onChangeQuery","labelBrowserVisible","override","onRunQuery","expr","async","datasource","suggestions","lokiLanguageProvider","history","prefix","wrapperClasses","labelKey","typeahead","provideCompletionItems","labelsLoaded","plugins","BracesPlugin","SlatePrism","onlyIn","node","object","type","getSyntax","prismLanguages","logql","_isMounted","componentWillUnmount","componentDidUpdate","prevProps","range","shouldRefreshLabels","fetchLabels","ExtraFieldElement","placeholder","cleanText","hasLogLabels","chooserText","hasSyntax","getChooserText","buttonDisabled","LocalStorageValueProvider","storageKey","defaultValue","onLastUsedLabelsSave","onLastUsedLabelsDelete","onClickChooserButton","Icon","QueryField","additionalPlugins","onTypeahead","onWillApplySuggestion","onBlur","portalOrigin","onChangeLabelBrowser","roundMsToMin","milliseconds","seconds","Math","floor","prevRange","sameMinuteFrom","from","valueOf","sameMinuteTo","to","RE2_METACHARACTERS","labelValue","replace","isRegexSelector"],"sourceRoot":""}
|