From d04a30a1119ff3c24c7085750b10623896fe2a2c Mon Sep 17 00:00:00 2001 From: "J.C. Zhong" Date: Mon, 18 Nov 2024 19:37:34 -0800 Subject: [PATCH] docs: add docs for sql complete and fix re-render issue (#1518) * docs: add docs for sql complete * fix the lint warning start position * fix rerender issue and enable mutlie select --- .../docs/integrations/add_ai_assistant.mdx | 7 +++- docs_website/docs/user_guide/ai_assistant.mdx | 7 ++++ .../static/img/user_guide/sql_complete.png | Bin 0 -> 66594 bytes .../QueryEditor/BoundQueryEditor.tsx | 10 ++---- .../components/QueryEditor/QueryEditor.scss | 7 +--- .../components/QueryEditor/QueryEditor.tsx | 29 ++++++--------- .../SearchAndReplace/SearchAndReplace.tsx | 34 ++++++++++++------ .../extensions/useEventsExtension.ts | 12 +++++-- .../extensions/useSearchExtension.ts | 34 ++++++++++++++---- .../webapp/hooks/queryEditor/useLint.tsx | 7 ++-- 10 files changed, 88 insertions(+), 59 deletions(-) create mode 100644 docs_website/static/img/user_guide/sql_complete.png diff --git a/docs_website/docs/integrations/add_ai_assistant.mdx b/docs_website/docs/integrations/add_ai_assistant.mdx index e22824df2..ce6977615 100644 --- a/docs_website/docs/integrations/add_ai_assistant.mdx +++ b/docs_website/docs/integrations/add_ai_assistant.mdx @@ -12,7 +12,12 @@ The AI assistant plugin is powered by LLM(Large Language Model), like ChatGPT fr ## AI Assistant Plugin -The AI Assistant plugin will allow users to do title generation, text to sql and query auto fix. +The AI Assistant plugin will allow users to do + +- title generation +- text to sql +- query auto fix +- sql completion Please follow below steps to enable AI assistant plugin: diff --git a/docs_website/docs/user_guide/ai_assistant.mdx b/docs_website/docs/user_guide/ai_assistant.mdx index 67074f107..a867fdddb 100644 --- a/docs_website/docs/user_guide/ai_assistant.mdx +++ b/docs_website/docs/user_guide/ai_assistant.mdx @@ -37,6 +37,13 @@ If your query failed, you will see ‘Auto fix’ button on the right corner of ![](/img/user_guide/sql_fix.gif) +## SQL Completion + +SQL completion offers SQL code suggestions similar to GitHub Copilot while you write queries. +This feature is disabled by default. You can enable it in the Editor tab of user settings. + +![](/img/user_guide/sql_complete.png) + ## Search Table by Natural Language If [vector store](../integrations/add_ai_assistant.mdx#vector-store) of the AI assistant plugin is also enabled, you'll be able to search the tables by natual language as well as keyword based search. diff --git a/docs_website/static/img/user_guide/sql_complete.png b/docs_website/static/img/user_guide/sql_complete.png new file mode 100644 index 0000000000000000000000000000000000000000..da8c70a81819336d659f41dc48a0e8eefc1d7c58 GIT binary patch literal 66594 zcmeFZWmwc*`!=drh$sdjt)PM+ARrxs;=nB-J#=?VH;4g9-bzXhAvKhAgGzUIj4}){ zlyozD{rty%_y2j`8}^6&VIRl)0S^w4nKkQot?N3k^E|KhLH?!WRU#^)GiT0Reeu_G z#WQCvlb$(qwu|s0_z8xb!s*PJ^ViJ9#pNx(XR``2%ju z;TQ9VqNGo+f6x3G{u8hHo$0Pc_HqzgO0j&(`M1owJ^PZ$eH51$E4YiQ!pkjd+9&pA z<5#`srW{tLuKZp8NHc2cKEWfZJT`3qbW!tcLxZ5>cdwqSUOjBAp^+?+56)6!e$0?3*O4kS6OIA-?B+#{*YU;`=9kwP&uCXwzqcn^ z6Kyb5@u;Smcg#ZZ^?qZ`82D^@9sSnT>AP@S)5`P15>DNCA}4Rfc;Z zm#vJn>Ar}cPCT(=%VVd*t$kOqsI9am(U-@8f6bc*fs7s2{6lDvZ^{-fm{uPCb`RUNH`EzTkNA>Fq8J zL-@>N%Dbs|J~6c_83h~l3QAq$X^vuWFxsf-9dJ9#sEFhXst%fWdD?VrY83OcxVupb z$#;FEd!*a4EppgKN6^bgHKHLeqC zOGI5{@=V99a-Vx?gL%jJ0!GR3-nz>D-SSqtv$wR!SiWzQ!=z2#uT2M=Clr^&;sWbiXD|jt`CKgI#Mp01%!`%tRW!Zn*Gi(zuxGw{ zaPj}JeQ|t5G47UT?0~$;f5;@XqfshA@-ydL&w*Jx?`u;`&FYyP(R9~sMOUT<12h5u z;M@A|s&Z7_+4PHBnyxnYr_PLc*6835j@-RA&JCc?lqccO;qSX%X*3*a2ML1TSnY+0 ztn3*U@IB#~v;O91&V%pHf-frYb><8~62X7{U@0e83zS8F_FA`kM{Qq8uGNB+?g_r7E; z(xpUQaWKWVRPXy6wQ5(pbEf>yU!OTkaGvn`9kGA$&z(5Rb2 z$Z7uWjBgavSB6ofar*nQ63gNBdmS;S`!ltVOWj=O;0u)u6x*UFt?oZw(oEEstn=`Z zYEq`x!FK14(TdDJeWL$fhFIza#FLF8E#H)QS^sOaR3Z=0o$meAjtE%8x71g}6vj)f z4dF`C*~kXk%O`B)pSShozrckFS4WarTSqCEG!g57NAXDQYZ9k;y!5Ho{LSKeOWSkS zTMybE@(Ri;yXU>XLeZ2050a`9J=FrPn?3M#ULNBa#Tl~FFtdnw_yrbPD3tb@F2u;4 z91PHBh}B6_e$Nc!mKlh!PCEye6`&ku_{RwPul-JPyD-MPx;&ZiUqATA59}*-^Exx? zOPN0Vi6Q!DRqA3%nV)rEkKg*|aQ=_?&b)WlH$}>wdiL2ruHiqAN7CmD=L2K+E|iO$ z;=G*sKMVhNhv@&uJMO#9%KiDm74n8^w+(~d6nKGA>!-+y0e=Ilxvm5lY4^h2)0{j+ zuGquu{&d+mv*A4LV%s`J&LpaE?PONtzs6(C8cUTln61mQqG!tnzqMa3YUo)MEw1Z>LK{ zdOTM;;`nUSR>~)QQ*vY?(mp;pUHV|r)H8ktZzp4JyWjQ50WqpeP{eqe^dYaU2M@Z$ zrkVt8*Wjvg-089i5rvvDw7_Dp!9+fu{ik{_v7}0|I9_W5I9O(V=AwDSq;H5>t63{ z$LCu+lPy;4pw~{$Gc@iTW@7FQ1w1^w;5pM zoiNt3a@*}0am0tD98vM;E-?DIawS$C?_pzyzlK>;33-_;QqAeO%+hl1MP?ODl^$V| zR#((9BZbb0?Ww_h{0OqSAqan9QN5qfH=P?j70Rvxv$UQRDiv|xFzC{DcVT~7cOaQM zjlHCsE$UcNTDCjiGqP2@9JQ#$bmLz>_rH8zjUutm%@^;57jo2#rdO&~*?&BzWML`E zEgi#&Q!;Bj@liNjF&u8XH<{w?WH@(-Z?UazAbdtvys8lB64{e8#cmIgvR2ak{$hUEM@Gq}!@Z55 z=su7!V)$&Q{I@S)-=cq)R0Td(7&oJ?^0s$fvd201n*P-tBeGBvv%4w8Ig2#J^e!T; zdNO5;Kh$?m)qQsW&umcHN2AxHJ3*Ago9nP_ZFbRCrL$Ic$*V1|U{vx_^K0v&53QK= z#$AQ{=E*q`dCX^LVY|f)S-%(hao^xfbfz+orssJ2FP zH03~0I~D)6wqP=&EI?d$lxbG^!YiC5Wy>f&esWQ$TIxV`b86?fP7-Xx#jKarn=K>1 zzUX7!wrP6UF0KkZ-sbmmtyWV>&KxKeweJsLl=h(a46WT?h&f&lp64!CEfVm2Os#ox zitueC%PbdDsPjIW{#t)6D8Xe)V64=d8q*w>uT?YnxM-Npi#tmB$SBjKo7*L4C$xrd zNqw~-%2n?;XV0!XY>GtjD$FsPNLT`GP2&KXh?AqOY=emZnRd{EB8G1Z1konOi-) zo#Dizrt*%N`|9#r4o5yybPgHatWkKJK$2#v&EM_mN0>zyK7Nx`{DeT|mS)j+2gJsi7mB>Dc7L(r!53`?-d;9I`;cv!%He3S^!XKUoIq;1_HeDNE~hyh zS^NfhBZKKL8mZ0f!7VdVH-F0R_p&potmIzTWi7uQ8r;WDSjXwtY8 z!{;!CN=#flMW7<$zNJO$RCahAZ6NW%;v^!)qi^5@@ODplq|-Be?ojBV$b6MY)1mqX z<|9m)Y}n^$+d!b$66PXpwN)USqEr?d$+JKfBfEOH#$ZUg$goMXNL8=+?rDzZEj5Hw z3XYrZv7Xr0JJITv{&TBLi#e5ci z*;{l2j5;0*TQPfW9VX>fnm13bDX}_wzkhzWTWh3{T-NJN4HKnGl?=1lr_TFHHlFvB zzn<$z>H+k6}$J?8ZGkr1GEneqc%_IED^yI}84qPwCgbGb} z39UZbxk@iuT|F63O#tuAs-xLS+-~ZKIX0MP>wowd9=v1IpU#G+rea&OW5`@>&lI`4a>j~KBT7*`_XP>!MNRcbFJwzmF3k1 z6-=QVdiR-@-NaS6Ze6XH;iUEc5Wmh?s}w9;_xM}MfbLO|_}q4H4Qfn5+xq*&`*u2X zn#G}@beL|hhtFn}M`MgfV%P#FH~Z9KA^-A}q2bTpPHp{hM_nFv8v=}mvtQKh+MJNg zJL9L=QRPB0ZT*y^9W=~-uSm*_EV}8lpp!+sLzjTln3i258P9&V=)ux$5Sk&iL*+$} z$(veO>Dax6nyGqi`)hlXm8x9lS|4)eve<;@dJT3zaf}x)}y;+*g7bQv( z#ihwPKD_9b3*~E;3C#1VY|s$*fahOzFHXF)dGEyhB9=|2miSnK-OYI+Et>oyg|4Sv zxVj^5AWLERCbI?Ua9cukp>IlLRaNhaF9mw0&inEr@_){P5B_K|LF!`AMG`u#)wL!% zP)u@0EQEEF%yYu&6M3T2tN_npmbRzA|J7^#Ly0i2s*qw*AZNjHnYOMCpK4}iN*;ixc8Ej;aP_z#$ zwp;Ulo`2+4`sS72DcS}?&+_wyf(l-_&M{^U0XKSYX5YeYTqYgdiP}0v?k2phcFlK) z^g&xQ8M8)c^a|;zKDyK8;?lr`lsI^CF!LJsS1TKV&^qDDq63h&TlekiCPBzWhqla)^Z7x@%tA7 z1)XpMKea6Bb27zx0X8C4)p0X^5@Dy|bF_sC=I#o})2jz)pl7J!GBHE|MHVa_MQ8it9G=htj&9D;WU?w5nrG=eR@=ip$jrnffTSn%rC54Ep)PwSZkrA~qR?-P)L zNcUJS!OVoqh5oAdA11tF{MD?elQ)Q6yYhKdu>1C?Y0&*%-bu%P#5$Gm#ZyIh+x1Ma zRlMU?{Yh=L2P>NA1J}Q(>U!~<52TvWFuuej8%xSjcWCdpG{QNgX`YjX%S zA3J!6x2Ua)6#&iWUgyni+7)b?==OlCoY$-;3DAF&_MKG^<=U`^T-SG|JXRb1sBLbm zhe)4-no|Ds4JYfEGZVhEG+N~OUcJa9vdlWi-FI(et~uZ5Xt8`DJudLE%$AT10OWQP zcFm38^|foNs=Yt}HUV@@HHcRC``|ok9L>L&QHiD*&NE_qWy?rfNKz zck1v*BNo}Y7QyX3{UD^(Q#o9?f{UB!JRS}DU?WwV0Ej>mJ_qSNR60UEAab%rg?A#HUs3_EoGZuu+Yr z_)|cL*k?)b3xPTyyw|x+-&0y|5ms-HS;Bvt{&;t}@#?|Os;=_wSRogi>h(6(wI5eF z8hD1aluVQ6C1LvtH=ecms#BVU%kqA3nR3e@JeUBrva!#pZnu$xAz!`5_&$;tW0aIx z3#n<-@r^+g!!A-XpSkWsO>z@>G>oizou9cg2+1S&^Q%@WseIF~(F&3}JkovzLSqet z3)!#4yW)NkmF>s`K_?blzGA!Y7bqI)Nnl!9Oxc21&-9lGRH+gnEF?l83rw%KbA*}q zr#HSO5xwoPQenEMwiN7Kj?>6x< zuo4&>CxZXslC>t=3r_H1YUZ^F-^8v2A&O|v!?ot1zk2~!&XCPS>vOn<)!f1jvU(qk zqoa0gYxic$=Tm}Gq@&q+_S=~rH8<%VuSYYuMn*$ONkY8-%4E?7vVKQc4VJcUjr7Jhj^_c*Q9ruPX&8;UpWPUG22H1eq^nf{6I zD!7~Fpt57KG7?#?B>%pc1V-bw~4Wkuu4qo+~69QYK;|?|rVq+@GrTr2SPSirqR-QXm=n%$G{uG)A zZ60|=U4m;{`93vG%OoP3JqCDP{JyHf_spj6sDvC`gmg3Zliej+NBQOY?GvBkSprtJ z9tHxqdgT4=rVb#^J-m1wb zZZLZMAo@`|>S=b$GN>xOpkqv97jgalGiCM9fmc&<`7#Ok$y%-GPSkS&wARXU>9~!i zMF(5igyQCMMPtlL$lN|E0v49IC6hlXEnRy-8BrRVlI(2tmbHYJjmkZg1Sawu4m6F zicQjo^DKh$jvJkP&0af`s>=7;+MbL15u2wpJAZB>0#sDGf_M~PX8*_{uf`l`)^*1!c4p3 z-Sfx$NFt)1wAa0b1KxkZHvfuFw=OGdy-#VT_Yuwmb)@A^ zE8rK%0T5C3au}|oI?pxoiR~O5zdu}ut1(=bdZzxuG&{GHrK=7brHP}7mUcCkXX>6b ziLt@yT)J5ok~J!g_=N?Qk__7qP7jr zQI5z}uE-oQ{|U3LJ935^eJt8zwWiFsi1rk6yyqQxP!0fL$A0|VAJ#D47-ZN?>k_!yICRdC6x^TQ+tm)ul<1m5$n69i3Vl+i07N-bzJVI+R-m6KFzZd3 zb}OQKDNbg`J8Bfp4=R>wT8Jec`Ayw4fefl!2Gb26);evyx$P;7zrVfIJW=6*iB#43 zkmILBM5`j%juNlv7y_xBa#+hjb^-)Z0f18y?9DvROCt>N{Z%fjyAyMws$OaZlK?95 zueUHViVIU_3V=k!h~5L}9fUvjSe9>+6hJ;L3o9k(O`tMlMntyz8>c1Zpd#8UBA-b_ zYuUfpTt(MCv{kPi`unc90f1(q6gsZS^X(Q2w1SSz^tNWHd4UR76IO4ZBCFkl9%SDa zPeha$f~4|ry&V%>cW8WL`txJ`XEU~0*5$wa>;@DhBLQ`j2(UxJ-fSGj_ax$bSliMZ z_F~Y`G>)1gX(`9Dvc2~Ek?bfXZEzGhjoTtp1pBBgb8e_t%mwKl8gNEeHt{&=UL0Ph z`MnDym_j`J}gPz9|5nls6UlIa_etD#ITi@Hti*{_BzXpFi;} z6pKUYHGEpvp``}$cy_Ala3G=M%7h!-Ph}wHu(BE~7;c=hy*y4a7+7e~Tc{E0akMpz z!A9${M{!XLI+_70#9X~T5JUN(El{FjM%6D|YS1^z^3@gC0uyZSg#x8{Y6x#2>}Wx* z{pbmLuge8W0F8U<*m;+_gGu`^Cx#QZxu^1c6kn=>y9HUG)J@T7={u}fuHJr}w5y$W z7Vn}M3W0^S@fbTd8}^{mcJ`_#&T2t0e9g{O5Ok7VL&dKNd{OA$0NqJcH*9M_seSx3 z$))|KSyj$08YVHltt*dos>{_3Y=HFrF*28`XkwH#zxrlcn}McPL8CucaLGP8M(8B& z*msCA>6yZ!TXf0E#M_5xZZy}H_xC-oa9 z3`W-t!+U~K!3eb)Ch;FMPYOZb|KI?iI`M%iF(6vkTR;a?_ZU$x_l`u7s$Ku%l3^X8 z(n;s>5$m$a6l=}*k%;EuIjB*E1Tjv4Yx%)(U#!N)a2ig>TIM|rP4M1d=&kd?3wB#B zB!G6vL<{PI4VMa<=?LH@I`eyTNct-j>^Z%0$=QdZIiPuLL|bP3W$uGiM!dTB@-xmuyo3z>L+&P3Pg4LuOsSNdyS(p66eP6$6h!(%BjGl}5svChCK z8}v=V?ewd*oR8#12I<3p|pmei3+gwTGWJkQ>teBInaKD2C-LW zs;#d8evG+`8pNo;UlG#3ycVQ&1HqbHvkFEbWJA`DNw908{5bfYy<+AQIA{`fHi&Oy z098-FxxyZhDB>|BASzUZddXg5RX8wTuY zXF*AYAO5@q3lR0%kEo2=?|3XH>N5qaTTP3K^y(7XnJ~)~RP`(M1`mVcdv;&>VaHro z+WEReEJrgScC?S=-GoBC0j6yLz4Og0Eg+J@CRtaaqF^>AdXu8KcpK7zP63k zo@DWO@FeX3Q8z45o7@%O4xyP8K@CwK?=W7p=Z2pj|A}5ejcPHt3bRI(2}1MXdsch% z`?-Y|xJbhRKD=d|$s{g(uv8=`(D6yd?4{`53?!)3kQ4%(y*oBsOAg?c3*beoBrnQv zm52MrX+6tM-u_)r(!5ieCR7$SQiekp ztR8B_AJ*Ce=AAte`v*==qMBYCFBzF}=DT!@?2xX)-s=B&-Y({FlD%Eyy;viHx$UR? zao1;VrbM6PJy(d9#-bFxz^4k713A zA@BDbRYv^5b1Pey?F~mAU>X_D(L0q8|DLJp7Hfrg-uO@GAmYoDZgUB1fWs0M-R}(} z*N>}gGW}*U@>Rca%RzK>-5tM1kG}yGo*RGdx2e`D4)^T-BJojM>Ao(1(T%GAPdf;T zo!YzfLP7b`c-!qc8vBKO5X*&4_xriuvQmb&;-t+7fC+3mo_NpbLLx*&W=4eHO#@u} zz-{E9NztVE9MV?JiY_|mKs&PWRYjdy{s36ub76Pnu6zX^rw6G1JWFly6mwZr{ zlGeQjZ1#?Jcbj2!muOyz?YV8ldk*^m%5d5gcA&oY`B&!tGm(mFb^P&B&>Z{wGW)Cw z4$yVN-)Cm$*H#jm4%WJ8ADAZ$7IDQ#M1CnG>Pve17AL53qKswc^oIrk#4yGOzvE;1 z+Enc)#40^NB^TmcxFQO2q{N&$8CVx*Y_-|4(Vi;~NLH3DqrdO7jyNt3<>n~`-EWZ6 zPZ7RbFF?6{8}Jw%u{^AK6|=DhZiST>=PKqBTy!FSJa>C}Q85&>0u1*e$s!7+6cMZD zxKhwtHa*OUSHu)D#lLz65g?oZ(55iREsH5!ROQ+YZ+F4=8Km7&)VWvxl+wFRz6WeN z29=!`s3a#+;(0`jjzEbR^JlonFw3>I$!xJvM>R`F1{HEC`4wA~<&Y~MxLF{TykK+S zAg+?CpzQNTxroaFR#AcFj)>01J4E5yLp_h>Jg09p-n0^^gIbj-F@-4(FYt+I(14F% z=-GzhH(-tS7Ncc3ytY%-yMW2id6x~iSyg3;Hq+sg^8Yt~c#^?6xKqvR94apTAMb91 zZVe2Rq#!J_7wt4;bT7)-SA4D1Kja!V`a9w=XJQ`BlP2N zY~s%?VNeV6RqW_ zcBFB;h3THAh!)~t0tho4qe_#p>gsV?t-&5!?qsEQ+#WlAG)Yq_3f=u88lx$TLC39O^=6W^pTcdyn;=-f$ z=6Qi*xpl|;jen1QkH-y<0~UN|478@ilCr zb{Oo~)omq>MQ~JssAb0aA^)fGK~29VoMvc_%j#5PmijW&+Xq0GL5UWRbm647N`y;U z&cV}u$}b;8qbvu#X94L|;)!ecaI1aX$@+`*!x)t#SN6Tgvsq9>y;6rip5_ZP&3ur( zL*vlF$q8t7oOs*#9$%DiEE0b>2M<^Ul8NDrtzR%iR2fthGlmHle#hw@tk(J5plb^< z5o5u>EQ;-u^V#or1)agPKkQI{&wG%M>(zER^6;LNewJ`lw^|{KiXe*@f?jhhZ`DIl zq+y_E*RdUaNQd27fGD7X=bBzm)B3!;PUZz3$QSsgR3`BO)W9(E`*5TC3hCelWqmJ7 zy4J@Eem`CcE_@jQOe_QIxkwgiS)g-WgB|{U@Y!kk)ysvH!TNh?wPVPu?`15IRh8TM zAnq8>4~!gaE%axowOJ2jDy;o{OF}-F$_1D(Hya=;mjl#*NeN;P%#l!5ZD)A~$xcvD zvev>F*1+8@tn@A~5y*ip=xP(cw>XE+v`(qB@rNBmlA1OZ#_>RrgO@*?d)4#w(qOq0 zLZkBck1IiGV}2y`bWkEK$kAulM_9m)*TRBu@U$b9tbk+9Vv~lb9o2|(aFdi`-)^-Vj zBwIk-sx|;Jiw=1>!xR*#3ne9jr&qNZ--@|;U-Y-BTuA5NnQ#cg=?R#C-WATAmAqCG zX8gAmz(tQLp&CgpU7!METK%}u*7ia@%?#3`aG)mfMYn4XvLS_5k;!GAv&1)yd5YtU zPDF&FG6Zbw@)41ULgPW|T>A@!IGIx7GNZ=0$}vDr<8V5t{C!2eL6X@|8lzAhsHtjl zUWlhkP!S4el4ECCHS!V1ScYjv9t@s?0|MWyQ1dF)6Xut&qsVwhCn#Q+Y>7PWj$lrxL0&PFV#M!b-L91KJZwvy_a$dPPRy~Qd zqs1jw+IY~W;`t~fM~+Q8t;}($muMo`sRZnedK1X3ah7tzYtLu;R7%D{f2`wZtOr4= z5)!_4@71ZAc83a}BFA}Nqx{r51dJ5+uT0!*`?6K@Zv$e`ZXeL71=aO!b5|+3?m=D% z0~pd8P^VbKwAD5c_Npt{wRYfX4(wgaMi#M@$_Zd2MgXK`sH>;Ydi7KWDe9#%(Zq9- zoFdkESy?%0o}z9St_7NFsF+dU19Y_)LH!7TJ{DZ%vma_onclE!?>z6ASt>*MC+^)v zT|5#*>LPl38=TfNyQ-S{_P^s2Xeuw#Hd!~|^=3J!$u zO{vjwgZWbfAtb9$b{XU-fXa&Ms)qGAWwq2?PDg~p@plsMuVX9A691E5{-3oMa3W)T zbDfrGpdgLH2S4WshvQ?AWSU&N5OqZLJrI(LN+;~w$Lg0={}wB=nVjxN9y>xT!`ioV zBn{s$(bH6XQOPn;xTw{|j|pzMt}dPnh{cbC)?ET~@gsmXNcF)Vf7Fiynq2m6XUK#B z>4>ZMA)d$;03C=v2?Qe`D8jqgPul8tGi=edc0VpN4G3&QiM|?i_EBDbY>2T*8sx zk%!tqHZyp8m6th@^R3uk+_w5vW^rk!622){MvxtS8X&%8+a2k+yI=crfk~U(*UNZ zqBLfi>+eDGs?p=8*`B^yTqx`DQn+zEhV zu7%h(K#Ut8(>U@zK20UQM{Cz`E+U{ZUnkkyBqx+DpqWiyS-zkO zW7h>x?jEr`#~$qUhIx~!i?Fb&Vr^>=;*}6FZLd`vN^%UgpmrKC4oV%2liU;OC+^@7 zOHVq=qVoehAqS7~+bH`}}A5Q`f%eu8i*A&pT0L-thhOjL3(iD5gA7h<|*T+9Ky zW<$+BYX9}0oD1_1NFXWhvWZAcQKc+mu@!u91S;Pco&t!8DneRgF{bPtBe4hB2S!_Q z5Wm7#oU-qbRZ7ffyp^OC3t`KLs3&ZepD0^CKQUL-k4nzUDGv7$Z|`5XWnWb%x@WA% zl6}!Qz*4335SbG1f_Tuj6ON9|(K`i=&&t#@;TC)2iJt(T0mDr}YN)_2mqgHLjp3Q6#|_6+E1>uILmbK!r~6L(TDG-#JQ(MkYkoily%Ka=afG3$w8E>KZ3 z7tW|-LPGu*YWm;&&;K+n^jLstYmMdXExnUc`JdOI;sBfM%6&R%rdR{aeIpJmL{6cs z0`{`$3Lz=aR0rXSp#iNV7XgMI2WvG*PQ+MHcqFZXCmh1Z{pLig2G}&<00;KtlKi2! zC#8Tt55%ncwU`2?Gx-0T?e3{v6Gz|!fa$GSMOB*&DpWS!4L2kkK$WZ6XX=x2@!UJU zY`4=$!Ztj4X|>|%(gsq9Vy<@MM@0EA*s7MrL~MGkKgy~y# z!e5)#`nuTWLW3XXzhrg3WHSyEU5})d_V+xg>w$LaNw`=LA?Y8&tVf*wyoE&Y?X_eg zQduu2_rrtGjOazyzEW+K-YonT(oS!eF0SUSeXZ`@5svM!Ww{a5)FOHp>C(Jhw~MA~ zMtaONwxFBw>oT5uzPD26UfW=CUT4LS8vv5gyy&!n1%)n;!^)~nFJYS$Q?7A{!XLrPB6IAw~mNweTK|LPd^jTU((1L#1P=By{o)xLXBEPvi*iEXR z(kCE2sdni!IiQG8*)wS#V7*Xy5P75TB|5e9L9y_xH#U|1562&ob*U#VSReP^Etq5~ z%e2G2>$Po^b3TxLl)1mRabvjgy+fT2W_KDMWHMIMVH>gSSC?`C$V~EFD(zIhdJh4es9jXA7(ghh!9(TRucw(`N!Uglg zx3&=n4wuWKk=|^);|_m0t`taApif~Odo8wcMcFFJ49qXB0sE~;rSmcsgqAj>OZq5@ zM=EvqS|5adR-Wn#0fFgQfaVlz_&ba^$1bP1X!PkSNBH)kI7j2e!iLl&wtG2jvT(#Z z2gRU}g}rGejq)zVZz9szk*7(*WDF320FFPeNp~WxB#qs3$A!MMXXP5`C$lnfn%K7hMkblEoWg_+*yn#YQiB zk49AFRN)bV4PQ}2l2oS&Gvmtx2{+AW1;D&h(I4&WBDK}^s-;3{?(XzL8=qA?HQD6w z0%GnB)VFV%yq|ldz_(iYguEi zqcTq$-}lOge_?F5|Ah}n6I<~6f-g8G&F=Xdm$a)@m)6pjgO2)q$T>7o_P3g@!G1kAt=Mj-QX}fgJt8Enx-iV6`JI&nN^-LPyK#;6s z9^YL7zRN#?asXp!CQTYqZ0p&%B}yparkWNrPvNsfze+lWbx$}d6HnU8Z><9#@yW%EF|DUT_fQA2RRUkA6J9vYR^{il?OHM#qzl(|%QP)G88RxOo~Y%z2i- zlC0A@jDeJD2Mq5L-gM3*`tZz5#n~aM*|n@7k}&$}-L2hY2i+hgZxjmhSqihswjbVZ)>z32)_;3) zy^z-@AX7><1AWaJD9rGK?PWtSGPVX(&Z3KhKRF2TiyYeGx%D`g6G z-(oFYLUqnnQ7~;zeKjS{C)#opDUlAYp8i$7vNUecUe6m^;=i3|=W7EZKY}7%<-OnR z;Cz1V#?%1G4+)Wdmu&CMrfv7}?VxZU2ggTR<>lq7A#a^eQVO8Y!y=JnKmeDHdh}49 zoL%cSkmNMqiUH5GyqzcDS_t4*rFcAl2OvWOn)6)+O`3Ab*I=uGO18q4O|MrLl~rim z?;5mmD_L%;qCX$D6|dWrIaNiKEslZVViFYTpp({#Y7m69Kth%I<0vfvQwmP9 z59{x8qy};|%b+QiMG>^G@fC2`IjV7S=?wP`Z=c!U_B%3^^Zwip28x$mIRq}^! z$q6f5BV7jGGRR%x-tDBfcflF|<9GSi5PR+T=5BYL}};Y%bf6IrD^$-u>@$|G)pn>@$J2=4^3iW!8B?$A#-2 zJ`Tgv_Ht8OR@G}WU)IyAwluj*M?As}@IyhXA54$;4E9DQ%pEYQ2f8ZnLdGPc`lWc95}y4cslb;(Ix#n$0>gWnKRB=P26P$H zuF|uAoxHtw#PoPBgIf|Fn3bJogYNX)JP&%nADUc}r)s^jUx!5D zH*j<6lfY?OgzIXuP%D0U%=$DbjIj7TXfUIGM|FHWIYW!R{$>I0IMa~ru{qVfPf7Q| zMH40O%8Wu!^?VTFuf=*T-Z)dAY75z(g6{Qx^?iqX|NA8HfA^DLW5M%5+$tVF&4Ipd zb{T9T+b_1yjHh}&gZFy8c_y2!33H0SL6SF^5#`8p0L4lIs0OP0vFyKnzX9zH18hON zNf>{D96OV#){;5?Xyfb+YF*!K4X})AS;y}py=wK)8D(}dhP=VPPXw)vs zEeskgTmjX<6_=G^0EWvTe|Iw&TD%1b$;H-Hp73)>Fn$9~JTc<)ps6Y*Fv!QX8pi}` z^W!`q*0}^{z zh8*%@n9yIZ0q4V|EKg*GozFpR0`ZUc_?g6Yv-bp$b}$VQytvk;FnanuA^VvYe&8LS z)(;}v{wGEsDlE{OXZ=D0afDZ9He{4{a$2;+ z68yL8uni2fm91xJAB7D=?nU6MY3J+078OU`|C`JNl5SIQvhA^M*lynJ%f{_(a=?@9 z0TJ{=z{mxSsQ}-I@trwf3JcL<_zh;Uv~a%m=C$BS`Z|4-u}5c;pU@VK|!Xe;oetCCLzLyclRt8FMJ986x&V4=ghja=xW$12{5pvxP`t z40Qv#CL=IOe%ZLw{&Jnxo3#j~mmlmfO=Q24ubP1 z$ui;axsI6qNij`d;R9~qcWJqQLC6V53XDe!BJ7r0hGC}s)6l>OFh5Cn>&B+W4*Yn3 zg)uvCMyTt4@{pQgh_R@IHxdmbpuaYN3`jmTS?Q!X3obI5aS=g^;B~l2N7XRUTr|3u zIAR9tVd@ss%SVY-U_?4(f4t437L0d&#PqYX9vcnDW8HMq@Y<~f zdv&aPe4p@|13+5rD~{dVh%pS!+Hv0#X-B~-jPykNfk#lyb4U8zx@|J)@m>RysKT{d zk)d-gJes2Y&?w(|KdI(*?(7@JYD>GAurS|qmk_Yxj^+4nX!a>Sx?5gEM%n8(?l4cK zF8?1-&v_OlP%pU9(nZ}Y_>Zt`s~OmmsY((wHqZ!jHci4pW3(L!LVS>6QmxobfphrK zAIIIrpW0NtLBC&wYsyqe4SWsXdJASLA06u-Kp6nY+o}7>RO9Nosl^>~TjwCZD>d=8 zcxdqW`W!TPJi{dqC5N@J!#$GiQTLq{T4>}b)w$#&ZpW-+8xs8)Wd8OI=z~phSbB~f zf}z$BARqEWrj|keBWQ36cwCAJr6R6YexMpF`fw{f!!EY%By^vr}0M?gGRQs_N2$LFd(=RY{#YZ^?l_+Y-8Jh1Id9=~`Ql za_u6qZA2nZ{cXs?LIX52Cmr@&Frc-~&=RhniDN_0Eo30+4wlPww^r7-AxM87yIzHS zS_0`-_HJ2LlszqJx$NaX-^_zJag#B}08NHn6;<)ekD38bE)hnjeVBk1Q2#zFt-G&C zIgtK;I!D=R%R+eC7mehxh3)J?@g9B!QfxKg60{cn z<>G$a)nzPN-&-}W5{F`DyN~elti-yc*S_jGMtWVz0|IIY;Og0 zbDq##TmnwzJ(rkrjWIU4506*@lSG3gWat`CV3VDj#e1vR?ul-=z{grXG6vy~I`K#R z(*cZ#nVU`jh!}q3N2@k=%i9X^7}dCR^Ge$nam5R@Wu#`((tH|i*Vte0CcVDUc!_Ll z?{c9CL&}{XhBpL(%+u!rlHM>JTw~KVUwEcjxhh@BG}*_7b*Xi6my>&7`l;i|!xy^~ z)qMgE+Z&>$ez4ht%DnC*v7=b`&iw+7WkXO}ms!+yUx~?zpex;Vh|Gk4e>=y1J2~m~ zN)W+KA`G+DuWaMYgs^9S{Q~*TK*{XcpayBF{9k$#<#q-1``{)3Ba5BXgLpG$`6TPD zjGrIh$n0k?^%Ue+%u;FAdDjSe0|{TN<$L$euducij$Zdl-Vip;((=0Ji|^++)V_YJ z2_fNm_!Wq~M{VyvI8Is|4Oh9?maPDgBYXGZ`w|vz(xF|T5zf3}A=1pmg`j3z9@7|P zcGR+HKuUcP`e?<)2E9C9=3Dw{o^6h+4qNWVoV!TO>~tINHs}(A z?;0T5KknVh{vm2%oc?Rr$rkmKp1!irB>=^5&U_}_6fqY+Pp9%ddGrDS;hooK{^6ei z1K*20TN8Ll9%pfyrvc-^w)-EqS#|fMj7q{{-DyjXs+C{NfJEY`qBziI4i3kP|1rQ! zBOE?^(k{BnaJVn=kyvgZn>TYuGKwlTBT2%QSuZ&$%zFv(Rm?Xm(+)8BO(xw)7+OW- zLuY2gJC@B%hJa`CwOd1A0&+ey_iF^IKQpAK_gaa$qMF#*%Ly4j$jCy#O|O+I7q8LW z)>H}QsNGHR$YpQUWx@2r$$PpllG+5D0IE=P6V%Aa+UMXjYsW^WDr`y6AeDnvFD{-?)Eo z3)?yju#T~`?ppcK$bH+)NVMWMuxWT;LAwR!=EZHni+NZV7WiLZ3bm!OHKh_n>plr_ zfJLj)p*$V@R-l>G`duG$*f!gqT`5_*hD*zV}OeMRg0weoij-bB}879Z`jp(Dm_6Fgu&*(VV#9eGY3l zEvVKVwftobB9`Iz*{Avng3kqUostDc2O({Ll_=&58Spk^W=lLF_r&zB3F1+QigpU0 zc~9}o>Y)|^9m?`P(fsm~d>#B_BDNODoE9nGL)Mw~X>OC*Lrua@E3xU&>Y&IgRAxu$ zXA{pXKP~!WAGw0sj2Zf{gSe{pM6NrK7Z_#OZ_#ah=|SW^+>c>#`CG$_?Lz4CWfioF z3e!C7I3$QsVyL-Qy_pavaDhR7krlq9ZhM%wfhz|0Vw2<4N0IU#jNXRT&qhZp2r&aN zpLltEZEB@aq4En>>1MGxIi_h>Up`Stnb;Lob0&o-3CUW0>2I4-rXkFT*h`=s$aCI? zJJww}@_JX?;X`qP4xJp*1Ww{~ZPeY9h_9J}iTV=T`v;F*>VIi2Ew6o<>^|$|!pc+0 z=`9D(l!eCZFH1b6w05DtC&>IdA<>Ul^%)e^bz9csA_9puWo}A_ad(Tj?C~O2K3(}Z z-M721vDIe#1n^6^eOEm0P-_3FVK>qUj7a2vO}DeNb4^~}II}#eT7IQQuc)F34u!QZ z&v}Qlvhg^~zZ76qEhR4RW-6q=0@U4{l4rk|bRwBuT)bWPw+OJC-Y<$Ffs#*tT@=w4 zeg0SM*)Iz{hB<6^GL~RAO-fdPmnb}280MuO0=J$6eW)CF3)eM{o7l!mBeNL~ zUA@0@NDQWAB(`~A9e(ANz4ss0z_ehUGo(VUC;(xx;Hov&5;1%q)|PDOGpIb{<{OW4 zSAx`JHunI^Q4F4f;c#bt>@vzEDQKF6_#|J~xrWj;9$Vq6w9n-7JK=U2B~dy683#4G zKVZ?@hI6G8z*meGYH9U4InECVd%Rg9tUl*fx*z3-5GXmvEAbW@HV*Itr0QUeq zb(BgyYkOP%DutAgMw0DT9K?dlIv$EaLYLiQX%xDed=Qja6%!G*B4`JS_B!2!9Og}dj?4l7=Xz}PzyM3k22j5Zf_iE=o`|qkfMPi+w*S=g`yC7(iGnYB$bVQxQI*-}0EU?;O7uG$#TyzS?|RbvwKfS+vLCs9z+0jZoVR0w_GeY@fWN^`Wr6=jZdT$?OWsR0m)f`J#gT_-aItGwUC zV~s$gYl*W?$jBc{v+hg2SNc5hvma63xa7)+Y4qzB_DDl`FNt&oeKK{H3)ES}mGQc0 zE3t@Zpl(p%!NZcoThcxYqBcMG&v zKfJ44B4jR9hhosM4_NyQ(&r=poN8+KkqXx!*wswWPo7eb;$3XAn!gUjWnPM+V1w*^ z&_+%C{rkf~Q`euBl9Ts3!PbA_?+wKdtkiw`Bufe5cYT~uAb?On5pn1##)3{+m z{ywO`#|OgA+_B%*fUuKkh;S&z_3FpDQh)@Y2=Txeqq<@>G$#VdJ6m86tlgM~Hce@n z`%)qDJjP92!{NYJsF&t&UV33vGqwEdGdl$v8v)R`P!D`ys zeiSe__ZNG!xb-aHp*n=hY>t+^N+(Kvt+J{ily%&s`{UN3AcBwHic$2j>lA!)h-#SA zyOLVEQwGi;-FUrZ=OC;IPZSHg&&k=!kexJjFVePS>qE5;S?i1n<;2VlQfL^9K_*>6 z?@!aO0#sd|h`sG}8-8F4bhX*+5t62%nUhr6VJTOGu~a{=xayhKC&GNM2*Qeq zVAfxc@}1h-qc6F~bL}4$;cuS%DmV(MrOKm<9U|BMv{pg9Dq~CAm1Whc6Nnu$#A?1N zm16CHHb}Gn;CTmNzu7Dn$r?yH2u*XG$ROc)r!%8yN1+dKP3*7|5P+F@#t#wlk0?(S zE}nlBbG4`tJ-RE$3t8E@qnC95;!W-!>}oh{M&erbry8+zGz!W`uHRU5kl#k7xA@TI zy}HiL_@t>jhoD5;pqohE%L>z{Lojf^5msD@2c93zm`w46fk4E@veM0)H)WRw+#hyy zblf}jN_L6M(rXl~@kQOt>m5L2cVTX{(tQY6#o8+ZZxZVZd+Rgf11a9U@IiirQ3u%% zg;v+Dt8;fmHTp?FxULh6jr*aX`dk5g=>FRVg@100-4uLaVuR(k_Gq1*n4WdJ_CS&0F6*9o&*T1 zUE)2|)bdyjia>`DXkV^6zcslmMz($#`UdNHy8YX0Oo}671K7*;H>)?Ma7ZA+W^X|x zS=ubxC1nR-vOol>IxteTn? z#l5aGz0=tys1z$iXv)kC?g4riL$Up_D~)WOyO7E4S@|(2{F2;VjsPGK_n|GBsjimX z`=#vmiqUP`Akqj;zXjYcN_Md4CgX>>S<{|8>;6R+tC6@y0W!5P5R-{9?26A8bDO@| z)@GY}u$|~GeJU;WOr~C>qnbYv5Un8w~_44SvffP370x>J{0s2 z&h3VKd^7uk;rA)f;r73n!XqSKVcG0Q9H$}&4!8ZJcHitfkM8M4wlxKbM3AX?sgi6J z_TPGdh|*k60+dzC?Rac^8}d@|{?w!rrX5P%TiR({F{Fijhx^X5Ui>LXf%X$hM>L z!t!d7)ppmex84;z_Ft$^_|Xm2`r@k_q1CJS5nguy(Jq$ql(hiC(qbUqWF5#5ZCeR} zc#LbQh->RKPt!m4Nl*0G{5xsZd21 zV4WaSb&b*oem4aO`BEuV$EY+Y!@#ra2MW9EIJcw;2wlB`!vv!A{L-9hI`s3`1)#q% zVb#dW6>;7yM)|O=Y#V0K1ynNt?~9jg@Fd$XkL+KXvMY1FA2bC=z)U0CH53K``-Pad z8nvfdcOrmnimTNb1Z`4qk}0k%3KMle{GcQA{BG{^XLTe%x?ccO%G@uayY+z5GOf|Q zmehty`s(W`_(_xzVp6M#{X{bP)RLLB16j*>)e5!>TFp-~iPVe=?L^W;%4zc1%3Z3q zkpPqzq!VFVo2)a=Zu5P4o4~zi5LswCW>TjMHKiA@jKQg-&=^!GM(9bf*Hg2t<4+yz zM=irb06yI)Vh)ko(eT{;T>t!}2;~~qkohBSnOvML3{1~x^~U?aev$Q?4tJ$?c>dW) zoIKxk0n6^9cH6sJq|RxZ$d0B@?o=m0D52|K7MR-=Bza7Q54;5h5K`&(f)v;dQut>- z%Jq31 zUnSWlE{Qy1^=kV)*&K~x6|Y3WzcQo6NP0rqP1JqlNg95~QZ<#yyUK16BEe@h@^tn( z&L}R<-j%UY*%-SDk2EPqD*43T`>!zJo%i1#Q_1jKsoXy$Ri`j_gK@fmj#;R->DFZr z!-rQHndK(Gt9m58CYqrBbpn#t3yk%vMM8!{_J@c^oK)U8(K9!m()k%F8!-EIpHzD42CuQBYZ74J%sKg^ypia ztw_shCT&`s_ESsRYr>>#+GdKHRFgoZDQ0V|!}VVP(*JWJh$nnB0T(U`^^ov7lj<_W zj~PfQW2bi`p0=^IT>y5a$~#G&ot^3sfim>9q-wKJDJ6v03v56lM;?& ze?;x7>DOxhy4N9~a~}9`p2}jPA(ZH}fgY@IEd^W05O5LICpXmq%AARasY|#2%HBvE ztju;CW;nEc`?(-yJRkNnbb<;P^lT|O%%OItIQx1K-kYq~9ZSmjxL zlM!y1L(HFppPN(uhc}(|+J6WfItHckDcIsLx@FCWuEX?3{AL|OoyfNsqyBR3!4=xg zPk6@4KT(l8dA48lXpTg2CiKEbBc0Geomt^ zo$Iklg7PSapj+>J3|&)bUn|+Vu=TIss0fgXI2%_LiKyd;#$JLT)V%vkMCklB1qgx zIlO-=eO`_v+!Ao!BHq&$dz;+sW?z9B)zkli+PGpKJlwY%7yE8Bxxy)!u+SsqR+P8Z zY#Uvh7I~c2O}@7$LS!6HEt&^$x1qj17neo(#l$V zLFuNh9@=rcxozdq%P;D}-X@QayUVF4QXsTzCz+L3e^+^J0^637@)+P%20W_9P`v=4 z+$XjunQXC~KZDWMQgh5my08KD8`!YaZpX&&u9j6TV7df+NNdc63>y9B`(4U0RL6WM zv&G^8SaNuw#bBPHZ)SHtAOXxhas3%SkrHZ8@+@C;*-$oal+H7Ic-$>hRK$ZWw51OKId%vL}5 zz06><240ON7%d9em4(H{9nNGjB;Pk-ynJSX@Vm0wwI@T$2Om+!@34N#;d@W>!0T9_ z$-Yg5@O;Q`v4D9uBUbA2qk4tCZGurAriQANe*sb%5Tm=k%gs9C%w-d4j2&qE-FW7K z&TWGJqAg=-|IILil2ZlA8gJG{j%qGyFRuoFXgsUiR!90g{nc9V!g22i#z}sAU1XH~`aLf-nO%&LskbBK^o&BT35A&Hr-qIqFc>ACkvA1rk=t2nGD* z%jM=B#Tzm0r zc;*aG_{el0U+?OfsRuf#Yi&QEp0`W?FmAeQKAj_qn4UEZ{f0zd5T1(5sL+(hBIKYw144VvVFlm2~;ng@NywymCrs%;0RW!<&U&gvDVPyY{P2d;26*JaMsuh==7u)#b3)?CG`C@ac0IO4+V`ewlL?&MH+h z$*!IdDa*0+b>)yO1@q9}A#nbid2ur6YaY%u@=xZ64EH~MyM`k={vs;RG(BNE-c`L9 zFB1=dP?Ni#!~KS`9L*eEi#X)_?v1fiQk1w0n2Epki#Db4YS)=(MIW}7>pgbFW3=BC zPxOzSP*Z#>cvQiY70GAc+!j~4*c|0XieWt7zg>>JmI2x#%VCn>Hh9$riR>h_;yX7D zjb`&DM7Oe1X$2G1kJ!SR8`{}}O#WRt;V{bzt!zCQjI-DqYT_b;6N|GeYku{7Yp+#~SN^IJrma-YK&Spa{K z)a6G?F{Z!_)NYN;Z&hoYosHf#+rVQS=!L2GHE-?r+S|#N^0=1|EB`7usB))U2;|H( z{u_>%FmET`8zhw_3{`qLUwLR>zg|1zFdJ}xh~IWZM}Kb8!f&X;`XJEe3vTVzzYxCv zca;T*dtv((yBDM+5}~XbeITlK9vHpnmz6y=?@SB8^yOBquB{Dw2)$jj04!ZB$*X5s z#ON%hiQf`-e$b9FR&&;(G+_2M)sfI}bK|VK>q5(jn_cisPT5NN6i1QU)F!i4D0gG+ zp?*gBq5pXz=l0S>f?T_MrS+Rg``hKKk=$#4OrGYBr-$`$vAgjv{j=%)pBgxrIztue zXSWDi%FTl%_fZ6lyw%~sc-6Q$YNGo2#$0a^pe5D-TUBJ|x`|QYoI0p(D!Pj-?+b;I z=5HGc)r}M_p0k0hjZ$P=k!9(IA}9{?Y+`SnXULxHG9iDND$@dTmM=cp0Bu)XKU z{zMqLJx&z}?36zCNB;l+JX^wmL%Ii;pnvFLbX^Y;0TBX= zC&=td_D7E%5xlyW@jW?uRzR2WMYs|8)KW3aSywtNjbH#KS3FblveW@T;|iwt_-DSC z0aDFH|M=C1iHQlOzNmhJ)bFSlOZl;-Z$q6)CYNqw^lm#kl+5K`{oj@QfA5wOj3HgX z7YA@tEOu5WLW9vjxsuvrnA$~Y+!A9(dW3BWF|`1D2x!?vinakk1Yh8h^t`uq|2~-` zp9f|OHINGzzBFA-qps~3Jj6E2vNKP1{T8apzI_=kh z^7cN)vBd``pPx#C6V%{8j5nk@0lwD4caKy2!0yhb*YGX{g5_&$EG8V~5IJaMY;25J zBq_~E|A}C{~Z`GR`OX6^=ahjVu1KFkIeekfWzUBvcvtEuRSrZ zXK|1$stCH}<#h35OzS^KisC0cqW;r+fG>evQz7xR_a|QIz?5~Vl9y~*Y93ixYbD|%3ht5|X&Q&TPKHso^@w;nWnV1uBAURxe zC;Rljzpn4+!MCLw?R zPz@Q&0Ag^(MCii($OZe$8vEn>i^Nkv_KyH#O!Fv#-oZuFd zdx7^3vN4RE)&Aj#3jl*#%77LotyK}Hfrk+ez%MO;x?wSn4|HJEkYLAy-HrQ2n&wXf zzyKHzk6IG%H=E_Jv%KjX4(<<4EH5(S-`E)GtYrX8F*w;q@0yhVB+Br^}PR{c6;9=lV z)dL1!d%*Qzp(k3246p!_%xss&k4iwyl+KMwFk6hvB((vBl)13Oyfu!c z&jwg+71N+5DDB7=!F?U6^5btYWS3>CGq%)DLcls;n4io-X3<{-eqY75E5d55x#U$u z{Z5vbhEsPwTd!`bH_IM6y94I3f2v`hh_1j)3Kg0V%BmTLl*`ES|!rxSCfj0G&E4xWkrhi&v`4{ z`@n&gSf|;{vHrXnAb1!7z7qzt39CGSu(|aUu=T!iP5sVUiI>=HeH6QDxg zj(%+DvoKWBiN99~5y0ia@y!Zieig-yDpg1QMkxEx#VcTR_&PZ$|N%hnXADTz>y!Nv7MyZe&+|S{C8CuGzmb=F2!h z=B{`0F+ZKap)(sgzPPO?e<*bX1cKp`%%AZ{-%MzN5-?#Lyil2?P_Jh*RNSNO=<|#&0<4 z=!r}NUo;r>y`PR?RTIdNAB1Y^j8SM~&wUFC8AsAzzWuZhRoZe8X%hEoXcs6-yboqI zD{Tz!4ReY-0xB|xx!D-#ch&Fs{BdALRzRN9dPf1e+BC&$h{Mk!i_WKboS2BbkVzzn z%>I-HlX5!b04amo1;&a-S5TQ7)MZY96_3hT43_7}t2|h+;waO|48U2Z9-O_>cUE3B zKU^$Ee@%mvuiWInABO+=ZI_z|Qa!Q0NSK~W|2^)T+TM(LD>MTYiLHGeunl`MX3x#T zvtS#)7n6xp0q|;#zs@!}#^6m=IC-gYTvS7Q*H}^iR&8XVv~@9}^L|2oT@4XIX5cu0 z_mT8nwrdm8ck$MfwgtVZ&qY0OOslCQ1gp zY~gSQxx{;7h05NqlVFl&vA}(_G$Aw%(f+7nHw1gNe0LUy)G?mcDbz`fI@&rqjK6S( zMLaA+3K_|8nui*qwk%!sh%#F`@Rk;ukJ5C+ZErzsZG94;a5m5Y-h)(5*Ix{y&gNvY zy*}ED?CI8yc-!GL5kS^65bD&wDxMipiT5JM7j>mU^kxL%GK!(`WFb#qd6+j=kmVei zv(-;tYiffaz6&U|(`GfX_fq#*cn~ktj94Nw(e30kpsAqQH?V?X{FhNZn0OdX;Sb@B z4`U8n6TMnWb6E}Zp7zJ+HP8v-_zabl2BwPCU~CgtApU*z4eV*^jr2|ACm+}xv&uEb zhaJ0EH(TJ!SfU7hy@E+i+DxT+1*qv05dREB6w;dIbw~y}Ku?oB3y|j4K$|>;G%-U$ zzqzpTmgh9Irz7vpbow(jS6;0_ z7PR=o4`dVXdB4dnT@(T#5mT_NxMYj?ASaunK@EL9jQ5L>~eldt>e^jM}Z+WcExL znYo+hhd}VbC*n}xq`gd8Xl1zz~N~kZ=Qk%F=dHM!WO`Hq?aOTZNrr>HX}D!kFy;& zN=!)j4s1)KO$qfoic!38PKJ>wraid^&x%?=p{9U`AYxyP-9p?U`)mK*#EPaQ(qJaM z&p`bkS44zCGKE7ylB5bU!9;TrI|PqZ`O+f6-U*{ayKB6BIlb5k%!nuIySuX$q29dv zj?&o?e-tQN>|Dv47YbL*nq6E?S=u$CXz&POp+;bd#bsg9pT!m^oEHKs`+~*F4XE5# zG^5`f6%d!dls(x}+e(rPorZ^3uV3EG_P zwjDrmq0X$-`YEo;Pul32&7s?j@C?WTaI+{n6y50sHD!sB>J}?e6{;}ps4m4u=u>|u z+g$|Dli8AVM+ZIh$KDXod1n+k%=@dpkkNHVyC><5dg+(2)$67Rq4 zgx*Pg|IJevJ3oPQCRp@$tna9@W@XUW4ZHx}tvWZRf!kOvP}}v9$u(Q)UsZu$FRJk| z2Z;`IkRnOtmW^HbUKLnr zyU4Wp`-1X7;IJ@earI}nBlG4lhH_vY#|JR?20A({Z-_--LR3>9hKX_!NS(kQ%XEkE zO0E8RsE3O^9l~=$k&Edx^mEm55SNk*l79vOA9-OQv>8a$yt8T8Uh405 zigs6Lac8?7LAWx9`@xw#wVC=={fWxo-cEDwz3$yHm8g+Nbid|{@)0ikc?gy{P`N4C zO&jvNgMoQAq#XqRT4IM%5;tv4V&3@d#UM6Gftw%Z&f>S69Hw9K(7L~t=g)dNFq|jy z@9yDy`W=kd+MR|gyvnatSrgk?7~^7oDew4?iVTYsi%g1BK&|Mf0GbBE{M zBYP#X~)66jW0jV zpQxl*2T0yUJSN%AydrlF!`X3eyJoaQK$H9h^y zUo4xh9i*Vo1MI+(rvwY>qpet`B(si<91!et)B9nTFBdk4S&PgGx4iyI%K|4ZJV*Rs zcGz{+SyLQXPl#FzKLJM4R2m7g2j?ubVks){k=2x{cdrqc)r(WPpW#V=eB-VlTH48p zmHU7C_P{Mh!+L*wAycTE)$||2vZyN$^WKdD0bgIqK8O#(uRe>ju0C%WZ)RqeN3;zU zkpca7ljh$~kkhUpWNCuP*m{^AwbFCj zF%m27!o@L)a3Xu@zaj7b6hPCb&%P8&2NmSKpXCoKBdd+EyL<-Kr)eL85Xo?I>AVT5 zm_ZOubL56KxQA*!DqkzZjH>?Tu+T4>_EY_($ESUaP5G9*2k>Jhw^W(=A8W}wa_ady zEX7H0X=g}vr1*dMQzf4QJNcpUbLg8dAnSltGWp)E*0KLHcUqgK^ zZ<(2mt&nVYzX|#`ACpouLhUN11xO~*5H;W$dIS@rnNc{l1xWMVq ziB5I^DAVA7_9v{jriy(6IZt5{r}3X&`KKikU*dvb5TVDGQHk*`f&5{!eT%(Xfr_!o z%;0XaUo^UeLJpKR@xx_6?;nBXLv*XqSCB)QEZ?FZZ8h<-JbdAwH7ZELAlrH?zrOj^31_R_A0Fu;@{m+pi}at}u4{`7H=-d5xxhu5e<-Rw}KyFEp( z=59AX2YufHa494Ls%syiP!0O9SzVhSfmGAZA(s=+Vu0&M>gCksZ=Pbi>a1LZza4zA zb17o|tnX9X)Vf{*jN<_C?eoai3>@#0`Cnt_lVQp>ohrpvAQ?h6de9Hbs?#PL`ra;n zT~kHnx2GWxkiQ*d?n=I@*`?AQOK(|R1&}FyfSDxEY?B7M* zO)qn34nK0`7Y)eE)Av8H{nNPF<{p<@do!}bJ@!^>=tp z1^iR^2pEfdr_q0N${|WX$y*EJnRReU11}nH>N!q?W)B3yMwwN(%{m_Vc7Ox96pYn} z%kj)ADJPl$J~ik0kPJGr>lC*wJTrh$29v|SY!Y7t-kPCc!zS>6bm~45P`&>Li=ym# z#q*4cRWsYp;9FZ(-(P?YzUqtuWN7w{L(@@mrXav!^)OASp; zg#Z~Ufk}9#=m#h?z6HslDX!zY-?+O^bjI4_!_dqMn72!UZa&!W0rk3g^SM*WeAA-bp^F8Cif}HxW)17W9l--0D#y4RHe}k8hgT@Hka<|d4e{pre zp>Rvs!%3n$Sh+zs2KJc?D=nV*x%H2VJv|};jLoF@^R_=J9Qsu}<+5k#_ z$2A?oZA7-JIbd^FQ6UOdr)5quAeL0crMq1LaZB51Ebw_<4t59Kon{?^9cI4T33x-A zJLyRWtRIshBHZfsahDl{;0>rfgcJiq=UGGQhz5WL!=-K^c-10aB#IM+)ZZx#vZ_!+ zpUc@X>>}0f$hHPZ8euh3D*b$j+F+o7<485!n(r@An?kj_v6kwD7Qy@Fdb7>Lob69X z!kk6BOGf+x%-JjTahO4^X{_Ex{le?v!3ovS459XZfq#}$Uz5c1QP$_EQ_saV7{_;u ztHLzM#N|yYz+pDl?l~qSZ#J0Bkp01=I~xq?JvQs}1V!j|K>K8QsBs*?@jqk2-vxKY z6Q&E^#FxnZdtd#Zwh+ejA9`_-v4n(#qrX)4MRKTtM|B_#P4;jZ~)kJfQ!OQ>o zlP)bl7PjB)u`xLIM;>sBContm5dZI^rvHyoY(fi!H)Fbih-~!JFmPm|jG|@C`Wuzy z^KV$=e`pQe=Uy|F(8H*i&ezT!`!c(X$al89Xe=NraB%$5w~PiL9p}Hw`f}{6W1seY=m8;p|g`l zIobuan+v1l=|(O;reJPT$_DYzXZ1aujVwJld*xQHtW~*%|5P&(qrHkbswnTlDuxl3 z+WKo_Tq}$wT=-8>Ft)~ea{Pa7*7sLDcioj(Z4xfWbKqN+=Y2lm&)u?$B?7RnW>R%S7&*vzTB==tW$wY z|8>?r6258C?jRtV_l<-PQEQ=rO^<8o{$MF+F3>}LyO*A1H?1yzR-_l`8$jTOv*KL$ z&ZITh_^U^4ZsD}nCVL8$N9$cJMv2`TY^d3=4MEHId@UB&OLQ^uC61laTk`^z10Tdy zhnk-bEO{3XGprRghO-l6y@j*XdoAP93C#NSj-{c2L3O*3rn`>WiFw-k`!HrGi`g8{EX5h-7=*(HG^~i0{nSIgp4@8(7Y`Cfi;hmn%ge77$dzN|6r}35=wF|ah`sFaK;>Jd zn-@5o=4rzn73IzKQKfI+Rz*5(%!X>Y@$wL@`qA`j0^dsgjoG6Hzf+w(JC+odx4~O( zqb2(?9iyS$Xc$4<7qKA?09i&;IxK!{sqKMb_`Xmt?m_ z%9|TnKZFj13D`gTZCXh?>r>s1^7fQyq+!2Y@kL$~4CZJwZZHq17Y-UL#J(zZm}j%M zc73>^nTsi9N0rsr#<=}z%;!6w|z`sgI<`8^A3vDY{{m733X{#a7-C3tAM`Ip-c`lD`x1oLz-v#UXz z(<*;eg1HP^xJc(@lc^sdEHfll4h$co)ps$tnkfyZY|7BgfgjaMq{Cr}pDCBjd;6=r z&JKN9LRM;yx~)Vbe(kNV`}E*OgXF|)Itf-UD@RaAO=jvAT@mW1N~IUyVRH*@eyY({ ztMO%K&2Q2`9grojA}>%;UceuHr^5c#>6bP0=)n&bw*otr$Ja01YTlCkQ{HpHL@Dtb zVUV=D(K+At$k$WOvJ~|*@wvnu?{g-uT*H(ebi6V}mLkq1^z#7EqgE&s+TU{Lb)jW5 z_6~J1(_LKy0}n;#BLFd_iyO68xMm?#nwfbrsEcfS1N8^-5(#g#su#5WP4#^6AGUTh ze^vp3RUTIMS$IpH|J{$wJo8`8bLc6Zbw206aq*`^%{>`S(v`NGPW$P;+hpWW=;CK> zwA`D>!Ams;>wg^>UtjEOtvDLhEKX={Y&~ksu9)17(0X?dhuY)D$FHB-_;#L3hbf_? zK(z3UNgUP41OC{Xh2x)c-X&fQ$;sz&U$mfq>||kaz)dA#EqyWrE?qFm-f*i_x$-2x z2==38HqT6H>Kw9*%XHNKDzCqNC zPv1=mk^WpbS@kxV5nYgR!VrYuVDto`4g0&tST@k}T{))Sh9xdFQP8{^`=z%o76ZzE z?H3H#2Mg`3)_U=q1#|0jfz^`HqDH}`(v)s45%qd@r7=46H{rk9-)%Ju$Pu2e%{_2J zL@?#Z(-!p+hWiU1wPTGY=jxUYPsuL^AvY{WzUdjq&PD~r#aX)U-p+nU4JUN0e3?*D zNtNwXI}3PYo;G| z9WE+jPOV{l`mPO=v?-HrUYG40@r3@D=vZpr$QP3LBxtv;?)t#qgH^dAOp5v0eAFGkRfJ7r41n_C;qdp2?qv1i2YH zylL8N-m@xW9|)&lec|jf+AtsTG1uQya%WDU59rP<991MTP2z)zW{}TWx?0zx)LHpP zVGE|MsaT?Bgwf9qqwIxXN#(Ibe#Kal17SoWqDs&CT?tI1IhL=JGF3@zN+(*-6@AsB z-$DZW6Q6b>l)@B}^z(}M+Yz^MJ^|;yed>zcIvSLr@s}B3=M6Kl^63eya+N3Rq;6}| z!|GRia5+Dg2BLV)uNS7$YZ_O?CoZh_x8D%mr5i;sj>WQU4cmQF z_E6L57+Q|)dIa7NPX(WBuTIjy(RiTpON^{X zoD?HxE+0+QA7rpka>ZopPh?XV^R2&rcazan zkU?l$D^-{F^yp32aCZA{*E3h>EelLs^nt43b8O|}*86c~X7yoQm(umJ{z|JH#n}Cd z0t=cCZ*E@gR3tgzag=Qtl_M7i}=uU)s-El=Os132D8&keXffrq2(&1aIN z7Gu^08y4E~hSmU)>R;8M3Y3BmE2)~EEy9kMkgYYF=m;jNjQKa|71egpC?=bKaT}8Y zuS;ibK%V(rf9ZpW>(OuCCB0Y@&C`nZvXxPQU7}3S{C6->`Eq27s=;}0Nn{~<2FcEHi%;a7Ir9&-k%-6k`4_18 z%tx9A2(53}qo`HXew+4p{G7m`{k^Q4{8HsTmzACsVLJ60Aq`o`iY8-)=wNGY?-*`w zo>%T>W*aD`jMuP9i^2S#q8F>#A+CkZEe>ad5@7nx=P1-vpUt)GSo<``?RZ?E0@}Ix z7HxcP$836k+P+Kl@@6#0JT0MIQilh?8m%Foy!jg5IDX6^(y471{X!yfp-=S&Ayc?j zi&3GVn>9@MKA}3e=#V;1@J58yz}KNI4>1*~(F?5MoP-7KBIJS7#&F)i+0c%BFQOm0 zs=ZubtZ>Csi*aXIs)FY17GjP?A*DftWK3ynS1ATTay``EP>3)1wWMqvW^+pvt?;_| z(dz5qh|C^iI#N$!Qcf?$ek*cHms^Agher$&mWU7Vj2+A)aSB&*81SiNTJr+YkvE=T`W7~ zGjrLs9mBWF&q_V-O$1~QJ3rVMcYng%4$HWs&M^MH;#4XH*WT8`m1>B0Ue7bgpxw-X z$ZFfL(|REvP7~R_D3a~@88&b6QuDgcocoZt`VAb(hvLGgvbT$ULCd)}1Guv^RTMMT z+s<$T;T@7g(e=nxvs|XP8}Hm&e=sfBM+3(TzNwcD3(;0fluo4g{sg)ls+iuou<+i@ zro)34{<9}Z990Dg=;v-(m$6Gt(ISn73I-g69e+kM38{j-^w^ux_}{@4I=?O=cH1|6 zPdUkZHE5&NHE+P^CC(mAyo8KZCNLLq)EzgH!$da8YVeK;h@Z?|2~ot|t6 z`r*P}sgJwR+=n|Mp)%y1Yh?>jBBayT8J=p<6#H2{5D`&=p zMtA~cD)!qi(We^OFO4ruw%8*+3Y~5oALQM&hXTNC>f4)iEnrJLY=OWUy#!i1}(Sz+s1xmrUT!;TAd8+{my~jONO$Lvs)$rbJlOxC3 z*3DHh#v;u)*J|%8>*HnBtWzkvl1ucqKHV2!UtMUVC6<#*rN?cMK|74&gptjK!40)V z6%`2sFC%~2lJ_4q7W<2oRjx4!6|0Q2P)n{Dw#E&oB}jC=q`QSH3!;Y`eL_R2N2JBF zaH&B9=IocS6Q&t{O3}prv2Luz?(eFESom{hsnD3+Gh;zzO0iV8SvPp@PVFj!n530n~SM5dQn6U3zNd6-w8m*Wg@yscbf~wA^n+@ zgDuqzM2>U3Ob}|bGUP!&zW!1H2DUathXt%Ddj~IUAZxEu>b;izu{#W_pG>^jB?3C|SqX zjE;}l_G`lbV)@NdrN>VBv)P9a6=z(fN>f*J{^w~R|;#^>L4U4Ybjx|`0A zjpy8L7n<6@>R=6l$cfW_>*EATO2FbSsP>#@95ZQ+F|ajmv3rd+OT{wN1#r_-CVC~n z6t51*81X8IU1uK9E_`H=z?@_IXE`7+IxYbd>3O~)zwQyuKJEU?oJ2o4hEjWbk4pl{ zbcd?e%;|=*p$rR$;wp)zTX853=EN`sY_OfA%BM#alKx^)M8_`(#pP%(u3w9>r8@5u z^i*OqNWO8D2(eFe5FU$5Nas{;mzPwH6p!B zRbm=@xION9<9XruNB#WoL<^Hz%d1^JQLr59B3~@cFEvMe>SpJ2BPm86>?7e3$F=#w&qOu>(Y-!ZIQ1ZJ}-5|mG>th^7wirY_ zzS0zgm79eSigC;>Va!G3va3zqDsvub=*r%eFgDx^UPg2u@0|R z{!{;^&(M%@ixlj0^%1vjN@?l%9l^Q&rPGb|O@#sGnuDb|`;7;#yoULx6)^$rMt;l} z@Ah=3&(i--dG8(7)YiR?o`Yfm1r!iP5tSpoh;%|zq)YD|L0V`cy^APF3l=&;=mbJQ zAb@m5iqZn16CeW82|Yjv33u~;-}k#?+;`kV?%&tH9DC@_UTe)Y*E8pu^Lf5kyTGQ5 z0u<#NU7m}BZ`GxTHVQ^Fu$h)V7`PY_m3UF=mTBH>aYXxhTRxsU3{rH)uxJaT?>(@c zkpx1>xn26lI+m9B3>x1L+q1jb!$Y2(P!k6t4pTF+`|Fcs^@jj22h)IIvq0)3e*q_IR1`4z_UsSIEOIHw>a-`5cz3dyY%Wgp;%f_2mA3NdGa7RQ9qk7 zH4IP7)cT#C+#H?$p=`|*_J@}eLX_@fn6D)o)LazmcE|Qrx05G~us~DuL=F{}1s*?kN)GlIPBFDicUH5vka#fr?i zlP(rE9lbI~2_xD=^@4fN)LuO?4B2grJaZ$IJ^m`vyX(T+VS|fsX+Ug>(I9Ng@J+Bu z2Na&Aa{28`UutF;P;$g0D0uPt+fn@>3F>@<0%hEn-J${DnlHQB90Cvi!>9PRb`W{# zkX~kb0hKv75mMY0PaP(0v~#UD0;R=ejQ~>ImLke)TeY9Nb!7;6f8K<}fJ0@}DaeZVwe7)rRD3V8&>ko?aR-3>4M? zb=1c8kDV}#>cq3|5ZsJb6h@$5OBZUl^Il%0?JHepa zZ!aE^^F}m$tjzj-dp3;A!6HK?J}w#f@7^rUCbbUnv}^_S#|E`7Y;R&jnK*g)`M<24 z4bL^$4=b(JuTD!FEUbT^JC~hlQ!Yn(?Q7r`@j^$rlqQkNsmd`_=YG*O_C7U-B9$t) zhn>Z1^ZDRv@7`qbQqy(zHySTY7su9KPErJN5w*f22>Z#=)zfM2u6Mf@I4%*Lg8uq~WMs5DBP3O7HN*W~}sENS6+S1Uh6E`3OJU_15B z;f`VWVX?aj8^&$Q0?k^Ysk3}{;3pVrUdavnSm~p$CYJDIb>uBUAYwC){ib;7{-**f z<|mtZhVUhY57xIshv_#;-sI}^%qFnBVKEG>w;_txx-ZO(xF$_+avSwroOof2PD0oa&y@2_QdLKdk^8FiKra&9 zaan;OGMbgRmx7cAjG~S8$=Nw%?{w1uu78jE8I3&aTi%+30B8r?1Gj()DhQ-2F#*8q zboHqIgXP3QE&9jOO%?@rsZAEBncsEY1lI!CU;8HO*(e~>Fqs`cqc)Ojs8Ji;%2UFb z*aKS%dWKsW7Bm^;hrJf{AA7;F9oqs`3gQhl`Y2Td^I?t|sw;^xM@@%J@^+^Pdd`%> z@Cm+IW`7^%yhwPhIMeb1RCzhaha}G2wBY@d&-DI57$!@$K?9LBo}XVoUXwj_kFq0^ zSLYAk!?nw=FGojCun|6714sN>9IhS>=eh*3M6b~owio_jEE&nmv1$FrsC`L@*U#+k ztM#U!1|KHru`32YRUKUELno(Azy5GTSLiQ37nfb}2|E9XD!xf6$PHh@tkTr-+>e2- zIbXslb!|b+oz(i8%1^7;OjLy0Ah)BhwM&-0ff2d5lY|VGyti^a$XBVB4#NiK8Tsn@ z38tAqXzb8Tueam1c=`KVI4`LAwK`3gH_i$j`2tlol{DSbtjK&0#B<@0`)ff3>BUlc zC6@`17lC9y{t)?ChYSKWdKkW+U`C?g>p3f?q2BaVCS}s*FV>_)962vl6Y%;0Q;nW^ zm{PkUE%Ak2k$cAzx82{?IM01}?`WSe%)RpyFM8p1$jk>8gIu%@sMXC}W1_6?#?k4W zd_cQD(7IkNZ;|s%pKOMy%lo6Uda!EM{30vEP~PdxCmfu)z1$#b8osT(ST;4u+$29U z_0YI*L~@W5pajsqF7wYbm;8r7eeFQ8m+`2Uibsl|MXFQv!<~JcKxM*W*q;T*=g-?( z>Fte53vcvh)V?$1F>8LlC0wqD6nCm#P}xZqIC_oGBwJ^Fk!?^ zz2sAIX7+^DeGvo863@YpHYO4O)DC-g5v^2d`&9BCJkn7^Y%%SEk`5_*^_E;vEamo_MHe69R2 zea9XfeLvQCH$dNyOAO4^3)loysodUKu62}h+T4s_v;ExmPsQ9GRYkAl)TgcIft>4o zB5HmOMW9d1p7ohp+8wz2kZ48DHf_Hz@qeG`NDa9Hzmok{>CQ!*p0kj1Ur-wlwtlkS ze2UkS89G(YegMEoLQF^f$n3o@pz;#c6Z937QV!>TiLA>>8| z8;k$;a?yNVQA-5exJmSz0CWBw!wJ%A4wNL?71lYpF}%%xpy%9~hMXH%NufJ#$`TFG zYtMXTga{T!Yp)a?1gUz(uRF=bvW-#)rhM z$w6&qYn5FQT&YjTc$A+LCY99uPll0Yd&NhdNkah!iJ%do)|bE#a-W8Atv8cuer&*9 zCE&ZDkD-1ejrfg&#yPsEkLrtARACxg(mY{_WI>s|{xcOG8{hhk4)+N&=R>b49h4!P zg8p5WPL#KQ*ePPBv}G45GWWW>EDliBZw^LA{=XuNh4E3NFX zJ>K}=IenI4@8EHTP;G`GECr68%o5jDf{JCwlD zaxKMji(I(S^nljCF%cK|q4gi5SA4TMa?J0oC^^T=@9-fQ9wXgRNTWF7K}MN_A6gzTAQwJn5~Z$ zNNYi8KCSD`vqSghl`g9oQ&gKRYxGN?G6YfD*-4Y2Jc zBB0H}ndHCzl6O>l^2ngXxeLj&W#W4YJLI}ph>XyXe#yr+oLI(K#V}^0Qc|$Z)UOWG zLIl~lJQ?uLl$*ylQ z;7pbn@jmX)ryg{fjC|PPGXL3K+oye05^ zI5kz_vzqK0Rm1-@jnt&}ce1@>mZfK4)A-hl@-kCKzN{cYy(OpZKRljaHf(P1s?8w0 zd*$}V3P+{KT4*)2WrRl@?v{&okoL*{U@jJO6>392oTsaGo7x)*f@YQ@X4|5+W+n+c zc5@lDbHgdteU^|kDZWC7<1pbNxMZsHiB&&e^yBUcLwo z;5=5_2txn)<#~rFQR}DT0TA6D{A^s$iuPQo6d_^~r}LZjBsU0a8;&&0Qvn!yj$!DS ztS~WT{C4rNcW)Y~7MXUMY2NQ2Hh@2K^#*#!r5A*x@2($hgt1_1-TNYx+F$VSznpG2 zZX<@y*RRP>XbIjIzH48Pt```HOVP^bKTx7czx9jnt;Owt-{D7+xyII} zjI=Cla<|$`p$wYl4h_*lpx^&HU!TTOKFxLsQ50E!t~FxY_(cEmRzrefWE^0B#OLt(F!*)r#N^DU;CmV~iM5gy=qY7Gm-K^G^MbB^ZNE$Dvr?Iis+7WA9Q?d~OOC=Yq z3hI~r#7LQfzFQ?j%_CLc$(E{}#ZAPI8nesu3696g9^F`dn*RL##K+c)Sz+HXzG)?5 zMtt4cpt({RgKBuK#O<&@IsT~mjhkrUfT)OPQGVSSQjS`^#f2}X(=&zIfu^Xc?EdiJ zwOwMyYme1R8`ndU>PCa)V*#I3h?M!)=W68U61L^qKW`ZAx)OQDJwKt^`q)4_*;ZFZ zG{`*fCB`;1dZXbAul`jP@oG54wKL+!qGOT_f0Jc^B)!g|)06cIfO+jnN1 zQN*G57ugQKc0GgCxt51de^|Dybw9q8tFG~|tNQ~a-0U-sKhgIOcZ3`AFd)a8J*g&y%&{md2N09mtQ37#i}3AGH~Oc zxt@dgHR1lE=F1jSD*4#`sqrfb%YONAm#0sAsJy4f1r_7h%aWQ(TdM|hl0Mg@~Z#n!vV@Cg#BA>V7^+*1rVsb$Cf@|>Qa z{KW~ux$2b-W12f`#rxBO$qWCg6#Q-TqBouOXdvgmFaQ76IQ{L!$iOWzA!&;UvE*Fx{A5ZMK}E)Sy^hAYe)ap zPXF^uP6&n0oVAjX`7Xq;dXm_^2lkWU$|Z1()Bh)+>HCwaic`F1QOB-2N~USVSBHa^ znc%=E@3U5(uWpWzxb~zasOxj{T*p9 zFf~V9>&AAe<>5?n|x0LSx8O(n_aZt7t_ThZ1w^{ff_xabvz*W;MRCndU!5Jcnu&S^A(W&ngeLWApiqY=fT#T z-AwD-is!#Reg)JI>;P4I6d`7w862+#cd{6N~MNlNBNIp-Td`^su&XignNcT1Atgv)=fR{|S% zqGaSj8u4fcdR}gYgoIQ84HRGJlg(|9$s|vJOrQP8d;Rz7{@0Vn zs;@u z*w-&jL&@S?U~tmPMo=jMDfVt-T>*Y1KyT652QcREhOE|u(Vs>*7p zWS-cK70_q3w7MD#^aou^?OLB|umd<$2vr8n04M*_^70LxB13Bc4G)!+9TIOq)D%S4WoqMf z76mh#XJ#X*ox-Zwz+P>b%}r7Uv_Se>=aF;O% zh_7Qujgrs)oypm66rP(%wYt0L#p5GI=G8^L@~bPc_D1mr zN4=shLGVeu;5NYf5qr{Q2gp&)&BhA3BkK++de_9`Y$M2m>N$wAsEz>&qY7g1@$>8C zDf)ahGc!s;XQIMRWioIT;R*0e%v)Lj9n8X^M+brR`cagO_pk7CXCv?H81OwZbPEOK zg&}~LHK-&0CQIinucyr%0|0U+W>~!Zb>9<^e%=kE$m$hrkQXl{x7>)%jE%g-&FZ?{ z+nf&wSt$YiJ-d5*fQDw{09KQR#S&1zB4{7~5N`z9*nekNfvbnJ&+z=0fBbJq5N8|y z;lePI&${494K6EP`H0T&%oxxKmEA6uPB&3z^vK%U8lcq^M~|HZvp}auTfW*Su-MIt zZE#Kw_*1H+r){;ZJtcFm$mHbn)#2UXjf#cg5!q+0Zz2~4USvCcef;EdZ+&!EZ{(}= z>)?J)Dy0ZCHw7P#%v7j;uZ7X9dH#5Q#~oNr0GIgEF;pw6!v0u(z5o9X3I6BZ*OjQ^ z|2T9h%BXzI`4C{7?%1oKTcE76lJ?iYhmR716o5ztvG8pMZ4h-_NpFLmDTX@cO(bs< zCyE01a2CQDzWqvfc@iV*I&>}k-rZcZ^^JW>rZLYnThw(3GLw6So+*BBQ)ii0=(xSi z$jEBcj}r9NMTNWGS}Zd-q0Kk12H8D~l+_tp|2tP*s9+CnKnV!>t$GnDz2TXEMrIx| zzj||-a9JZ8#`gHh{FnL7W{NPRDiwa=sj~E#eq$z@5Z`u7IyRibBU2$8$VIV5TSlu7 z8e83`V1fP$pJ9R}8v?s00zIL=_`t%Bjz>pS?{2Q%yP4qSLyDr1{8gyb0-Qod9& zWW39hm5%AM-#eIhPH*F9UswIo;se)CsdUEEzb2cF+U!Q6)YVmZBFhbkSQ12Jh`b8C z%<(;iBAQ2V&U`Zm{8dSgI4; z296i`XlIxa^^g*q*t_DSRG2^hzR!kcctLciq69BH7L48jU?w=;B}oiaY(}~^|6?jl z7@|$V>;9%vv-#54rSn5R$y=k76+-5VPs=(n5^v#%%ac7jGb^=eb;y!lCkuVJ>+b2$ zt5M{v@SnC>S+jYb(3%Sf|7E~iE!$K%n?+ceSZD0h*4Bel^va;YZ z#PtRw%4pYE8taYq24>c_AhQ{eF!cl!P1*r10wQ|?8%P|Gy~G|j?G`pdS*(MFn+d%h z%78Nm&LM#MDQ&}b7vOhp14zVvm^23mc>DOYbIB8aq1{WSQxbHmD<4y^(&4%S{i@0N z!{M3gcJ%gfXmTW4dzsc_W$g<(I?*?IeNfk)=V>CRf1lK1TT1h8f#h=jr*j4xxLD}l z)Z-~9ha){>?`J6yx&1m+`w3?8TIh)e`edb#)$r^=YZYUF3|7D(SuVCY7FBDwO9?i5 zrNBm|M9x2|f)x4~^WYlRm6>@9L(M#gn-q1M&J^bTJYkbM_;y~7p~|7RYte*XI;406 z1z`i-V@pad12B{fKtlc=%Mw-!;Mf+;5SiV6MZ$HZ@ec>3HOcBb&dAULIT?=AO@_h0 zK>_Z&7!ZU?f*N#(U$PgRCy7rOI}?>L*Z2@FQMu^wn8=6_E1iDN2hb) z9z-EOIxOmn=nOsWEY@7sZW;m%vIoAmyZc0XyL8D8;IQ!Q7N~tPL0Vd?LiMe>PB+#~ zyPqH8J9ORiQgCekZ`APLPk`gNs_uQRCEqoJT|@G?6BglwT}l-@qZIFL!k_&?Txn`Z zoGl=^ESiz)TEY(Mgd1Q0gSlyJ6=2VA)hHQO12D*q0SczC0^3t;ZzsvcO3P7{z%aN9 zOO)ctGAzOVtjdM%j`tWMJqq2L-0D{lk|s?#{AG=(dpbh^bhk#nobU2Kn2E9jc%HVx z>4Wd6CrE4HJL7MTTGvi_q*sIYebU%ZpIqSl^Y-?RTk22RX7BCGX)ISh8$Tpnwuz8t#{^ z(3Nv(Pekul!5qDP&-aI7)rYP%Q#K^=YDL|uPu!d5GM-jobfo+EE&V1vRR9%8Il;O= zA5UB!d7B;}jl%{5^6I30cSoQZ9?TI}uRaX`f!Bmb0_uMBAaWvbnPp_DDLx{}vUPl4Ui z4L3S#25F;O`DG_sRijQC!Du^Ulrcl*EgyX>!*kKU3|I1xO!M&i#G%5XBCZYIw~=UF zM`wxL)v^Y`n9Nwc86d#ik%$E4Q^g(Ave*n5DuSMIdu#Zhz>Va!GT7NJ3`q`2t!L2pw5fA z-UXYw9I$}AbI077<`J5P6dWfE*OkMSz1V(y5aG#G6d|$TZaQO}GIB#X%5$qebVUqn zo*4!C>((Cd<96~tX{{Vf17ZEal8XGqann~*z#oK~o7Hl|@uqR68;%HaA|;sX78`)M zlwtzo%SxP#$)?)!iq87l$MGY@b&9&xbc41lO)JF>K;kGBxNUC)C>1JfzQ0bD3D|zM zZd_(@0|>Iap_VVcQ=jSL4Jmf)QO8B@n1cG8B}d^Nrymmvc~tRhV}nju{D=_BUlde? z4qd_JIq7SYlvhR?_6q&Dc{%l+vw>3AlU&md6yTX^n{Eo)0iUP4wG@`s6%-VN9cjEk zbHcW}^$B{E-y*{nej?rmI+hDL+?CvFVlh2;gX&I_2 z%Yh6`P00=kA}O&Erw*bJsagE0-tp1MwpW(Lo@? z^5m+&D*CqYb+CM61YX@`@W)H6zy@(Y%U~xNhIe76Xu2$eUoui|zj$vLk zo7ZLqe&W)0cN+KE&=EB$?~Qa>SuU@t5&`(M9+(W17ZF*CEB=y)YtSz@PdCHA!k=A% zB@FByxLP)jEC%AzGAEQ$FMfhZba} zSx{n0-0#IxrSy!O>OKU%mT70@#hb!IoHM{aHxb5&a@%HnusAa}Z>Fnk#3iGm5238Z z=F(PGICUayzj?&u^<%txiOQ+d6K51|G|v?&l4_9kx3efrA6Z^x+2o_&WJVg+FUrCK zN}<3IR+hh-WdV@(!lEnq%ZB3b2sM*=aU?ji9ie~B=ywu(@7;9oRjSP z*`vvemH*Aq(|(v}gl@Ujv7ub5F%atu z*L|0U?KNiAAWHP*5&{neJoIrve1|Sd?86JNxYITX!<`4LXU&o-VAnc|7YuGc;9VJE z6y=2yZM?V<5+<3V?z$ddr18ltF0jQahiq7u7Vj_*r+G2IEZoov39q%{2)PzweCYbT zQ5`2s37~YM5C8u1PQ+U;aBsb+lY#bEZhXpuj!UC$*6_;kN|8|jqB<$LRz}Bw|BLtg zZK9bEI7wo{I)F4AlsCtOizHTAE{aXAj>w;SDn2-*E_v&q48|u_-iYsmUtk$#WFBfv96^o)KnbG=wP9Dgkt0bFmJX#F}z%?2-&C!rJ*MC20_q zs&6mmxz5p!54jjRTj6(2&&I}hf~n(TJkPB*aBGtc;e$_2g*(ll0<=s?f`!5TVEbZs z#CC2=;Hntfalo${rQCrSNuVgoow;(IA1iFKS(s&-xNoX$t@ODsK@yW>cr!`;q|dV@DH(zQ0{wj%Tae%BmG+L7+rc;~-XiuV^~15$?X^3In^-X_%P*nvb}&Co>E;8j0CP*A214k?sVN&P4LQm<2W=Qi^VL0)ILfMAj-) zKj=|K1%HWC;_%|%$TPyA4_i6Ls0Ha>5UBKpyQxLJ;TkiJ zubQpY^~+-X5oCysoA;bc{tno!B&k3coHS})l!SgL=adcW`xk;cXF&^Go}VV%`WJM~DCOh3DF`D#-6@^)48 z^$pNs?0iB9*9!w0QC9Akf5vqQ>6+=Mz5~Yj9wJWcaBCsd@bYjQEIU;h9GA^o_pX+k z`e88>%=9s@J^~jzvtFV!fN^xxf;CSwj^AwjIy_Ge`2Ip3jK$7I!i7pojNU|-80o3n zFkJxN@jAun;%V=A_3c^s_5)qS9o;7P`DeMv?g3RxK-Vu00_pp}+9!GTarRH4zfWDl z2jH_YcHQXLk$g|RNy8E<69cdhtG{!aCH-H7c|SkCDdG@3r8(+mdL=Am5ieW@=aM7l zWZ2CfEc?{5^~Hpo-)|>3%Z@W-4h%~@2t_BAm)l83$(InVwkBjfiFwCzkhJ;-a-r?k zHS=cYng?n==c-YV+5^+(TfP}7Z4fFS(|VRGnnQ#V1CN$I2z5@TEw-_g5j?6{c8ua# zMy8oDLDs!32&?@UpPM&J>M?YV?Jadg+O1Z2t?@0})~|N9-#_oz4y^6WO@1ni&Ds*- z9SJIuo2&{mcO5&lFc-4Uh9RsIex3eF_zU@Yed__+d;!BsomQ+ThJ+V|n-v|URyp`` zmPjkGy>%3*7q>DCvW{a1Nol2rnX(D2z$=62_h(zCjtf%7mk$n_tef(hl_Q2$SVbyY z{^-;&4rYa9Y=6lxW5)Q z5{6yV1igtyPZnvVvy58%=vQ@LM_Nk1#wlRS#=`EfnU5U#Y%NQ4oJSqAoRJ=D4zj%c zx_++Wm~VRWaOdEVUj8<;Wnsgvb&TiC3IW|rm5Bq1iBRB;hPb{skT^)pEbKwL#~~sT zxT~CChjm=PgZh4j=Q=u}pL+AsD<>pE4OjO+vvc3*BBM+uTs`%p-jSCa)BGRS}x0fIr+LsA)lZu$*TegkWC1O zq>4b&j|#_)kyJ4sXMXeDoKz_vwXh8DotM`d)o0+N60)D(9@{DYeLCV`Pbb9XsXIH*VH6GGzEQUKQaKdRN!^ z`F3nVQ})UgXXo?z$dOSAIW~|8bbQ=wu}?-;OKQEz^qB2T2Y0jRAZPVdMUbKlc^2E5 zfiZFbN#lAU?=slCuZ2E zkY(Zq*GkyRojzxSRKpOE#Js<(=*T&7a|+Fw>w&C>64YPA-}8Q+1jXK+mTOAi0iWm z*6d01R4)yk`|f{0@aSl}ST$!XcqkEIx*pxLC$32kRkB*RjRAiv3%Sos8PYl5-TC)cR#4orSWc{Ab3(GTsG)Tn4J z)6E>o<*(K;>z?{{^Ec_+K8^P&CX^lcIs^tcF22%#EerNlg_+lv z9kJx;BjT9w6yb^$fNA`_mioV&)UA^nJC&+X8ykdZ7LVxYImeF1wC>s3@&loPaVc>j zbLrzse^e!^6FM0jx(50pYt%$m_#Dz&zE`UOI#=*uU^!Oq7JKui^}ak5G&f}Oa;<&K z*e{q<+%@zrtwGbZ!9YlNcZTyPNLs^kC$ziuQP3>f-ufMU8h@T-S77%?@9R>7Ux>JS z*xK>CIUpYzyI|38O^#4$zUAQ>e2>;&GkUeWo~KrjMo11XGG6x7x(lMyQ0zZc1Eo@O zBZ8lv9(ur3Yz98>5F_M**p{rNaRA(gw= z#kIz6AWfqzo(Ls%k9`fnzthG8=enyz*75r&7xZt912I|s?2zQYkjCt&Wa zDYJ#fD$}?nor@87H&2sDo0MI3({$7{XFcxrkq^P_I82mU?d$BWo3eWq3U#+WImTcP zW$*|4jyv^&&^f@hOW)DiZH4du!OQ!9Z@I<5$tz9Rd>i(eR3^s+_)7yBaJP1NZcVTN z=jr80NV7ZCZ_m*(7gT@&MV$)g_N2#8ah^VHM`?~mpSzH1J3EUYUqrddbW9Yz%zkw$ zdMDQI7u{`X26NxWWcK13VbDtfOZNIrY}=7tA1vr=u?N03Xk+AWHwe_nz0@DS=kMQc z-T5bL+;bX@eV28y^Ab#-T#zOXc-~AuugNv9N)%*UkUphXnuDIHsd+h#ygfy%>8P1b z+1cQ_Ma&{E7DxcMmI+Fo&F0xKrgqs=!IpxJB(>gB(FC31d`_;dV0G&gr6ynEtx++l z`c6%RB%;D{im>DT&%_JMsLITD?m-6$e7^EEE_xPexJ|DC9%!I>0QP&xR_jF2T(v}s z3eEi5SoPh#HO!TueGimeZ6hKy@WqxhG}_Q(5=xr9=_hlzG27QkMoI3air8&^_H%4t z4SAsF4?6-E_O52oosYTQ{aV9i+W$*q_YtuWC$s=92+x%emraq^=*-lF221uB7H@sN z!DSpcX@mmqZj8!*JU{i;BwU#~xu@v?s0NV5GBo`w-z=MZnD?=gpTIGAda23rxGLRE zuRS-kUfZsoj@H6^V&hVF>X0mGr|}L}s<_Io=T+sdJ#pP2(PK zV%pU~PIi`6aYH($f>%Ra4@Xe6I|M|LJd3=2b zB83R+ahPxw8Xs^z4xb{0Bu#riUtL+db<;9)Zua+g5`okwdvk|(YOcr;n&c<0&K$VC z-3Z2z@9GTIly|h9KGeXo>Svyu9Etu|DeKa4{_47!m00k|&COyEo?| z7LQ{ilMkmFn%}>TzTNA~BFz^{mKkI2+uAPvZ&;CX#8Gv40txpo>S4le8o|uU)zW)1JuE7^)VtQla2)m^n;7RUU zULUpEod@u417Cf|)1L_%LBb$)w=eK4@g0Y(4-!JMeXd`~>QGcx;A8P9rhC#%tF?_f zW}?4CNy*G-nrr_*94Y_k)bkD4G+;!Bo|(?0=lalBoK=X!;{gXc@XYZoJD@w{Lwyat z3>7JzNb+vm{ngpxHr8}LaIRo9?677LxH2P#k$Vruy|6zMp7NEy_x(rOw`1l`e{=1~ z;M0tujiVdg+v~>7q1KI3KiwafyZZC5hi=2S4m85B@<~9Tu=+zW&5HF6Wk?FL0bKfxecnXqSjg zj_zg=2n;}+wUCn<5p@_D^t16epz|{;BUew~I=#J02FWzPU)%Ep|2C5&657|BZpNyR zpw5mtj-y9+PFx5FTUyQWw{>!*_s)*-MqKqxcGSA`?Cx9RMf+Z)+U3DAl_LHFowcbJ zvF4CP$JzK^c@&Y4Yyt#uTbb-(;(%KX9Pqnmc0cy0MlFNwv$EdIv%NTV(L9hcF2#a@< zCg`hMd@{1)>ZB=RU4R@jYZthT8b?Mjj(IhEx2CS zQk7XDGSP5A3r{XY2Pp@eRlO2Q!LcO#8As zEP&RKb!>nL3W5NQcJxh^cgFqFn5*1rVZerMTGKg=x?2M-*4?8m_;kNhNUfg0q46l2 z=>m9Qh(|!R@swMZ^5*+s#^ZZbUGO*;Kj4<)nM6zWVU^o^&Ypnrco1t^VJ;7&Y)7XN!p$zW*92Lujbn`r zSEj0XYBnYqM2h(1D#j1+)=~GUv-jA>l5n@YAN$6QrAnuZ4|3)Tfs)-^Hg1kzaROC6 z7}y$+bqBNADdpS!so5)wZz2ZTjSRI1s1}z+{?GwLM!N1IzDHi=W_{Y>b*i=hhB2Sy z%D%b~jCU;UW0dl3bnAKF#_Ev_J!B+*`&Sv%4m{8U&)w^HrxKuN!UL7801qq1Epy@Y zdN2kU&n6xtCwIrdpz4v@+iujMZR5sgp=23Pjo(X*K!I0WR#sLdrnw-K2Vkel!*YPFAzYt zO>C&5>(qGnKe65|sc;Acvb4Sq0WN_>MWg%7s`aBREiJ1{cqqAFzN3&Ge^zgyXyAcv zdMI!iRwC-VHny}@3I~_0pYFy_Htp{VH2J04T}Pr`!%0`w)e5|`%qGtLIvwf$Ck;)c z$&b_SIuxw}>6#e=WgZ5?_mk5#1q${APc^OoY?erC8<-RnqBuVMQ*?g=%MOrX#YUW` z7e_y}r0@m0ci6m=eK}cI3LjlQAA?RmJUqNd9edKCa(UrH(({ options: propOptions, keyMap, engine, cellId, ...otherProps }, ref) => { const dispatch = useDispatch(); - const searchContext = useContext(SearchAndReplaceContext); const editorRef = useForwardedRef(ref); // Code Editor related Props @@ -81,7 +76,6 @@ export const BoundQueryEditor = React.forwardRef< getTableByName={fetchDataTable} metastoreId={engine?.metastore_id} language={engine?.language} - searchContext={searchContext} cellId={cellId} engineId={engine?.id} sqlCompleteEnabled={sqlCompleteEnabled} diff --git a/querybook/webapp/components/QueryEditor/QueryEditor.scss b/querybook/webapp/components/QueryEditor/QueryEditor.scss index ac3de8013..46633c46d 100644 --- a/querybook/webapp/components/QueryEditor/QueryEditor.scss +++ b/querybook/webapp/components/QueryEditor/QueryEditor.scss @@ -35,19 +35,14 @@ height: 100%; border-radius: var(--border-radius-sm); overflow: hidden; + background-color: var(--bg-query-editor); &.cm-theme-light { .cm-editor { .cm-scroller { - background-color: var(--bg-query-editor-gutter); - .cm-gutters { background-color: var(--bg-query-editor-gutter); } - - .cm-content { - background-color: var(--bg-query-editor); - } } } } diff --git a/querybook/webapp/components/QueryEditor/QueryEditor.tsx b/querybook/webapp/components/QueryEditor/QueryEditor.tsx index e0795ae8b..bcb249e17 100644 --- a/querybook/webapp/components/QueryEditor/QueryEditor.tsx +++ b/querybook/webapp/components/QueryEditor/QueryEditor.tsx @@ -14,7 +14,6 @@ import toast from 'react-hot-toast'; import { TDataDocMetaVariables } from 'const/datadoc'; import KeyMap from 'const/keyMap'; import { IDataTable } from 'const/metastore'; -import { ISearchAndReplaceContextType } from 'context/searchAndReplace'; import { useAutoCompleteExtension } from 'hooks/queryEditor/extensions/useAutoCompleteExtension'; import { useEventsExtension } from 'hooks/queryEditor/extensions/useEventsExtension'; import { useHoverTooltipExtension } from 'hooks/queryEditor/extensions/useHoverTooltipExtension'; @@ -55,7 +54,6 @@ export interface IQueryEditorProps { engineId: number; templatedVariables?: TDataDocMetaVariables; cellId?: number; - searchContext?: ISearchAndReplaceContextType; fontSize?: string; height?: 'auto' | 'full' | 'fixed'; @@ -109,7 +107,6 @@ export const QueryEditor: React.FC< engineId, cellId, templatedVariables = [], - searchContext, hasQueryLint, height = 'auto', @@ -270,13 +267,12 @@ export const QueryEditor: React.FC< const searchExtension = useSearchExtension({ editorView: editorRef.current?.view, - searchContext, cellId, }); const eventsExtension = useEventsExtension({ - onFocus: (evt) => onFocus?.(), - onBlur: (evt) => onBlur?.(), + onFocus, + onBlur, }); const statusBarExtension = useStatusBarExtension({ @@ -313,9 +309,8 @@ export const QueryEditor: React.FC< return true; }, []); - const keyMapExtention = useKeyMapExtension({ - keyMap, - keyBindings: [ + const keyBindings = useMemo( + () => [ { key: 'Tab', run: acceptCompletion }, { key: KeyMap.queryEditor.autocomplete.key, @@ -328,18 +323,16 @@ export const QueryEditor: React.FC< return true; }, }, - { - key: 'Cmd-F', - run: () => { - searchContext?.showSearchAndReplace(); - return true; - }, - }, { key: KeyMap.queryEditor.openTable.key, run: openTableModalCommand, }, ], + [formatQuery, openTableModalCommand] + ); + const keyMapExtention = useKeyMapExtension({ + keyMap, + keyBindings, }); const optionsExtension = useOptionsExtension({ @@ -367,7 +360,6 @@ export const QueryEditor: React.FC< const extensions = useMemo( () => [ mixedSQL(), - keyMapExtention, statusBarExtension, eventsExtension, @@ -395,10 +387,11 @@ export const QueryEditor: React.FC< const basicSetup = useMemo( () => ({ - drawSelection: false, + drawSelection: true, highlightSelectionMatches: true, searchKeymap: false, foldGutter: false, + allowMultipleSelections: true, }), [] ); diff --git a/querybook/webapp/components/SearchAndReplace/SearchAndReplace.tsx b/querybook/webapp/components/SearchAndReplace/SearchAndReplace.tsx index bb08402d6..3b07b8f13 100644 --- a/querybook/webapp/components/SearchAndReplace/SearchAndReplace.tsx +++ b/querybook/webapp/components/SearchAndReplace/SearchAndReplace.tsx @@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useImperativeHandle, + useMemo, useRef, useState, } from 'react'; @@ -68,16 +69,16 @@ export function useSearchAndReplace({ const reset = useCallback(() => setSearchState(initialSearchState), []); const performSearch = useCallback( - // Active search happens when user is using the search input - // Passive search is when the search content is changed (isActiveSearch: boolean = false) => { + if (!showing) { + return; + } + setSearchState((oldSearchState) => { - const searchResults = showing - ? getSearchResults( - oldSearchState.searchString, - oldSearchState.searchOptions - ) - : []; + const searchResults = getSearchResults( + oldSearchState.searchString, + oldSearchState.searchOptions + ); if (isActiveSearch) { jumpToResult( @@ -195,15 +196,26 @@ export function useSearchAndReplace({ setShowing(false); }, []); - return { - searchAndReplaceContext: { + const searchAndReplaceContext = useMemo( + () => ({ searchState, focusSearchBar, showSearchAndReplace, hideSearchAndReplace, showing, - }, + }), + [ + searchState, + focusSearchBar, + showSearchAndReplace, + hideSearchAndReplace, + showing, + ] + ); + + return { + searchAndReplaceContext, searchAndReplaceProps: { onSearchStringChange, onReplaceStringChange, diff --git a/querybook/webapp/hooks/queryEditor/extensions/useEventsExtension.ts b/querybook/webapp/hooks/queryEditor/extensions/useEventsExtension.ts index 508fcc9ab..1c8d57704 100644 --- a/querybook/webapp/hooks/queryEditor/extensions/useEventsExtension.ts +++ b/querybook/webapp/hooks/queryEditor/extensions/useEventsExtension.ts @@ -1,12 +1,18 @@ import * as events from '@uiw/codemirror-extensions-events'; import { useMemo } from 'react'; -export const useEventsExtension = ({ onFocus, onBlur }) => { +export const useEventsExtension = ({ + onFocus, + onBlur, +}: { + onFocus?: () => void; + onBlur?: () => void; +}) => { const extension = useMemo( () => events.content({ - focus: onFocus, - blur: onBlur, + focus: (evt) => onFocus?.(), + blur: (evt) => onBlur?.(), }), [onFocus, onBlur] ); diff --git a/querybook/webapp/hooks/queryEditor/extensions/useSearchExtension.ts b/querybook/webapp/hooks/queryEditor/extensions/useSearchExtension.ts index 112fd3f8f..e2e0d425a 100644 --- a/querybook/webapp/hooks/queryEditor/extensions/useSearchExtension.ts +++ b/querybook/webapp/hooks/queryEditor/extensions/useSearchExtension.ts @@ -5,20 +5,24 @@ import { SearchQuery, setSearchQuery, } from '@codemirror/search'; -import { EditorSelection, EditorView } from '@uiw/react-codemirror'; -import { useEffect, useMemo } from 'react'; +import { + EditorSelection, + EditorView, + keymap, + Prec, +} from '@uiw/react-codemirror'; +import { useContext, useEffect, useMemo } from 'react'; -import { ISearchAndReplaceContextType } from 'context/searchAndReplace'; +import { SearchAndReplaceContext } from 'context/searchAndReplace'; export const useSearchExtension = ({ editorView, cellId, - searchContext, }: { editorView: EditorView; cellId: number; - searchContext?: ISearchAndReplaceContextType; }) => { + const searchContext = useContext(SearchAndReplaceContext); useEffect(() => { if (editorView && searchContext) { if (searchContext.showing) { @@ -30,7 +34,7 @@ export const useSearchExtension = ({ closeSearchPanel(editorView); } } - }, [editorView, searchContext]); + }, [editorView, searchContext?.showing]); const shouldHighlight = useMemo( () => @@ -80,7 +84,23 @@ export const useSearchExtension = ({ } }, [shouldHighlight, searchContext]); - const extension = useMemo(() => search(), []); + const extension = useMemo( + () => [ + search(), + Prec.highest( + keymap.of([ + { + key: 'Cmd-f', + run: () => { + searchContext?.showSearchAndReplace(); + return true; + }, + }, + ]) + ), + ], + [] + ); return extension; }; diff --git a/querybook/webapp/hooks/queryEditor/useLint.tsx b/querybook/webapp/hooks/queryEditor/useLint.tsx index 51769bdd3..b497a43b5 100644 --- a/querybook/webapp/hooks/queryEditor/useLint.tsx +++ b/querybook/webapp/hooks/queryEditor/useLint.tsx @@ -8,7 +8,7 @@ import { TDataDocMetaVariables } from 'const/datadoc'; import { IQueryValidationResult } from 'const/queryExecution'; import { useDebounce } from 'hooks/useDebounce'; import useDeepCompareEffect from 'hooks/useDeepCompareEffect'; -import { posToOffset } from 'lib/codemirror/utils'; +import { getTokenAtOffset, posToOffset } from 'lib/codemirror/utils'; import { getContextSensitiveWarnings } from 'lib/sql-helper/sql-context-sensitive-linter'; import { ILinterWarning, TableToken } from 'lib/sql-helper/sql-lexer'; import { TemplatedQueryResource } from 'resource/queryExecution'; @@ -75,10 +75,7 @@ const queryValidationErrorsToDiagnostics = ( suggestion, } = validationError; - const startPos = posToOffset(editorView, { - line, - ch: ch + 1, - }); + const startPos = posToOffset(editorView, { line, ch }); const endPos = endLine !== null && endCh !== null ? posToOffset(editorView, {