From 15289c367046dcb76950907d8a8a948bd31f3ab1 Mon Sep 17 00:00:00 2001 From: skulidropek <66840575+skulidropek@users.noreply.github.com> Date: Tue, 5 May 2026 21:08:31 +0000 Subject: [PATCH 1/4] feat: add browser apply actions --- .../issue-232/project-apply-actions.png | Bin 0 -> 92000 bytes .../issue-232/terminal-apply-action.png | Bin 0 -> 30702 bytes packages/api/src/http.ts | 9 ++++ packages/api/src/services/projects.ts | 23 ++++++++ packages/app/src/web/actions-projects.ts | 42 +++++++++++++++ packages/app/src/web/actions.ts | 2 +- packages/app/src/web/api-project-core.ts | 9 ++++ packages/app/src/web/api.ts | 5 +- packages/app/src/web/app-ready-controller.ts | 12 +++++ packages/app/src/web/app-ready-layout.tsx | 3 ++ .../app/src/web/app-ready-main-panels.tsx | 44 +++++++++++++--- .../app/src/web/app-ready-terminal-screen.tsx | 9 ++++ packages/app/src/web/app-ready.tsx | 6 +++ packages/app/src/web/panel-terminal.tsx | 14 +++-- .../tests/docker-git/actions-projects.test.ts | 49 +++++++++++++++++- packages/lib/src/index.ts | 1 + 16 files changed, 213 insertions(+), 15 deletions(-) create mode 100644 docs/pr-screenshots/issue-232/project-apply-actions.png create mode 100644 docs/pr-screenshots/issue-232/terminal-apply-action.png diff --git a/docs/pr-screenshots/issue-232/project-apply-actions.png b/docs/pr-screenshots/issue-232/project-apply-actions.png new file mode 100644 index 0000000000000000000000000000000000000000..437feeff65247924b088267e65fec2d8be453ab0 GIT binary patch literal 92000 zcmcG#WmsEV@Gsoc9%>XQP~hMt6ewQYp@rb?4#gdc1c%h{;_k)W32wzDxDy~)a1RhX zZ_epC_qiYbU*6~5yURltdoP`twPx1L{6bWeq;Z~;J%8}v0gkK;Q0>73EX@ZG9({lM z5c7sjPD%&!-yg1O(&7)wM<{k4Jb3*;7WhHKGi`qfWS}Wa{^WSeeH`a&+}pbB&wtF7 z%`K(dZ7nP#f{qR`7Ab|?psVKWxtL)|$9Q54yubT-@Rn~piyB%y^|4BaPV=qvJ-jl;OH0bz z-|<2@4CmiEgW=+ABzD#a^L+4$eFze5$}=o(bFUosH(URH24ibq8)xUMPRtV^!O=hw zvHI@W$G<;4STUw!=hJ_4b$^@Lx3yk!|L^O2=8bA`s!Zd5n*95&@ZJB&hBlXe^b)(F z_uWkW3zCr}0WMzA<(Zj_KC??BdV2aJF<*YqZIyYpqxljmdtcuh+=C%Lrhj_;jQ+lw zn88CPh6*eAVLOk*?-h0>ype`_I;u@b^?l|*B)g?4W1EuZtykC$IQ1yBPAl>kt*~); z(}g=!5xs_RNU*0|y|Udu_#9z}cPsM_&5lI-iWy>0XenU z$CVDSu;A}ujV0kc?D+p|`vbwVJX`qYt?VGcm8mn)Q z@$OrGLH1^(d%E46L39ANL?PD;`^*C6yGIXkDTJ**TE7QA{PLPtG~;Tr$aPC12rozy zSnD{MANTsn3yST#ZD$pk?UAMC*;1oc&sA|ibxn;KSx9Kee481AdMu;x)}|DYoY&Eu zDJeNQ-kEXw)-Y#+@WHSjr4(Zqutl*e1RwbwBy60qs3;D zzbMvLcjl)CLV_)!DG1~lBmTj14FeN>VBh+1n#j#{cq-7`!U1%O*{$gto-fRAtU;^JU7l944({WsIpl6c%=h&I}V>*S51GD%55mOyFxt9o*7|0y2$ z2}**pZ^R|J(f1OumCi>+2jG#2Rh{*fHbkaxQ>sE7_%wxlL-c~CefpN3?SpRv9piV6 z59+-W{lATh{Iz;jjH1C?Vv?-*&c%+)uV^%N6V>-w>?n!Xx-*VBgraYR>;S=cJ2API z?jN1!nz|e$ELghCcXqq3C-NAz0Ipg(HH0$am~qXr_5~UHi*BUVYu32udD!kO=HHap zK&^;_xDZ~#LF|_;LPQ~LS$i{tT_Q$5TCVfgQ|<`vB5Q_t9h!05&+Kaxja%DtGy?K3 zl~M144Y9;C9|iQwV(g_(9X^-zeO!iu3#k1q)Mm8 zYQ%Trpw;EPSk&+O9Ri#o%DRHB#bUgkAI8^UzBBRV+he6vLBwgEJdoRB zcgkimpHj%(e)9(@Xm?8B)A37u*}RF9^ zwFTCQdjNa<Ef!KCTwG4K}tzv@zGias98MMZ_dfg%uFlMm9%XQSg7@qKi{1Or*hlu#xXW} zdEt;PaMj;U?QjuH#s6Tr>Sf(#Cpde5!7P0F<_m;q{hoDS{2sNr}nTu`-7 zt&iet8G{_SLB(jW`W{{tos*JcjtE6aM^eyaYnACICnXW6MrMde0>*FQTUS@thHf5C z(@miEKOT*w33SDcCUFdp&K`B2tUrGIxT>nEc&0ake74@WT@sr(L&ztBaR*ibzq>(s z*u#~8O-)U9vt=cE5ZjL*S0p_=*b=#XFM}B(sht)ZPRxWOB66fiTJukDuaK=i7cW&M zZUR||_s(`E$H&KwX3Kf>s=Md9`2oTJR@Q^;W}%?2`9{0?VyyhJ`FXG1sUoN4mbUG~ zdsfuy_IM6eB0JjaG`FV4HH?^*WD)>IqwepIwxG#&rlzJ&R*CWH!&4ORK7I7|zW%W@ z883$@(XQ~#5IvYLL9I(i{`v4rU0q#K@(xDU%1SgixH+F=W77dB9Vl^wmXa3jpd!y8CNkaGSOyO;OCHB($?n)YbV#&k7D>8=asvhxjNsjFlvq~WkfirxDCAeYaA@Z97UvMj zI5OhDj&8(9^QFAats%G~51kAZ?pONUQqupjTKFm3y)FcY?VygtoqgBF~+CmWf;O$|*C*RxKyScg{ z#E%?h0Jvg@b#%O+rgQQ`U!X>(ptb5-BgI{(C7ewJEV3T_Id zkM*A?ms+nd7BOlTYcTpV3A40#QaNG{hKvNv8bjXl&?N^eC@SV;148;oM%ZX*Xx<%v zQ;cVl3Y0<}EzxG@$rD!?HM@^4w*p^LQ;WG?pTX*#v^g;|7mJ|Qe)|fTTU2D@=%^}J z@XrD8Adk6UW=roRu3HI8VCi`b3+}LgeDWZVYy9=CNY<5@cocGdN*oU zEO=*xSI1^2?5H%_x)ngS@a*2{&`B?flu&o-#`uq+Q)I)#Kk$o4ljdr7?GNYD7`No7 z-ZVY7*go@#r$Z~t$pHW&A|jhnqwIQqzusIlH3>R9J41uEx2-iBGuo)sje7FsKB-g| zLqZ69`D~{=_ZysND}2&Dgp`4piWmw_7ARRT9bdL|fA3!V!}k>FF0{4jK5`KIy29K0 z-s^N@#sOAuzm$-YBIq>%Ojghe{FU%^h?T6NJi>7Yzqhw{rbIik$CNQ%j?z#B5E>B? z5gwxX_LX7^FAnxI92^{ng{gtD{-{Q?<>h5u9P*T;q^VL(yRKeEBnexS-;KM1Jqx}f zg_!8;*PnwueT|ll!(7|u{@XeeIbF7Hls^Su?d}eoo(_&FIm*ST7z%ys3<>VJAGF)F z#ASmt;|cKOrgJmM7v^!D4wg*pZROKH3{yb;h~9Y zq%k=@K9PCulA%yyaPY9>JL{IAGa@Rkz&H&7A&!fsp4dqD^6TD@gYvq|Xz=cOY1XSQH(jcy?jtj3Ll5WCs<67A%a z2NvmtJ&n|9wp5h))IX?Mk{tiAKsnvT#f6O5*E1}EHIdc0&FW~mvs0WnY#O4^*ZdeK zxPN@S%C6qAhy2Q5onCRF)}h&AC;_7=OLgj4Rx54|^!1xDpUVvmL;5k>1yjUO99net z;{~8tzusupajD6DkDfS8z8w!^^BszP>{tNp4YNXz78@0T7^~@Mp)6GgFg`KCwA?>H z$WU8bJL5Dr)-w(2>J3*bnmSn2O;#YLraoGmVBvp*`PZOzpoclN$H!GMzn3GaD-7$~ zFt5nSb}4X$XlOEmTgnaP<>ga_j!+3@dKZUFeRpelffu-WZojV-Dosx_eM~9uQVgF| z^HYeVk|l)e$CsslI!e8uEjXpKwWosTL+p0q1%xv&EKG@&1P1c#;`>7%`r!cRf5Wo*FCB3JWf--8Ya^ z1ORxOk%6@F(qHADeec^c>ygi)CxA7zOxFxSFyX|IE>d^=NSZO~<%larGk z&Fj1~VbRX6Q)zOrFgB)wjV=GTG*gXLz&m@w_#79~lAFJeHfIusy%=_H*HF5E;NaSh$JtX*Z@Wm0V-g6v)A*ZGghO3x|&vEhie=P&&Ruh^4zW+#1#HHATQB*aRcS|qWOrU zJ%fDqF#lCbw>{1(9iTa%b<5JvXTnwAgKbfN$pIOjKn4|+G`P5TJf^~e|J)^u-xX+5 zFuuPZv^hFp&e%7Ed#~o>Q?YZI(ZVx?vc1vZq-H$rx5R}d`t{r9VlH~O&54*T8YtG} zu(Mcqgg<%gznLc2ELhJcgCK67TB zyoZLneJ{~-0bx;f|DR@t*MTS&(O(#Mf!_&msh9Q6*c0sJil*9|aeDWT`!8Per})qQ z{A$*xJXLI15?FRn5rO?%@vK-CjsM(9?W=G1EM`HX(a(s9i5~|(2JOxaL!o2iGZ=&9 z1s>kb^oM^v9Jgc^UTCzK$$T~4fUK5n#BFT9jKiAAA4g^#=~e>cp75D=Pa_e z@_4@nH)kv1$|dY%WSSUs8~q@-aN={|h_YpqaQf0Mf=^P7EjamPL^h=EvXFS7#U7+ws{Ctl~3AM(TK_v8ypx zST-vem>AYOdqFPbr|hO|N1DXG0|rP&aVgq6>LMQD^H?uf?wj17M=}2kCqAc~}Udn9wg@#sdw56cvVvhcj-s?+;v@+Fwmm=n1!aPr$c& z#pZYF)h8$R1f2u&GsdUCm2})?( z?X&8)9)QAOrTjKtGn3%+;%`Ah(^!n6OXhgOpPg}4mll`jWX7lDGG)SgPj-U&q>@AB%o{c*xdQd?(9~;!Q7*#FAaPqPePk^*YY@&Zj-N#=zCNp?=t?-#Y z=w({N1;N738iUnGN_s(?LXkTh|iSeFuMR8M?MaMoFU|L|E z-Zv64oQT09n>>Gq)S)|VS*M3w&~V8oB-|8DXIDA(18nE#N-VDS!fQ(A;)fNKSorB8 zUK`SEi851j6iNa;r+o3Or87=KpRD0^%XdL{KQ83^R*&zml-i>cvTSBghJ1yUr|gy? zo{cJ{RF|jskS;ra+oKTYXv~ioOH2Pyzs$~mN8r(jaN5XazXbhiSGsvKoeJeXHx91z&sx~CuEx+e4I6$j}NxIO8P zrYbHW8FVSkYLZ^oN)+%MaEiV&oe2LNBS;5Wt4u#s9`;T=wuBalg^lh&3T?Scc$Bqc z$P)-Ex8>YFb}|rgA1K&4?I11Jidf)tN3E=V2@66~Q{!4&kp?He)>f|i*ynd7opl+{ ziJ$Qg^-bGbICUVZBfP&m3FGH##Hfq360O_vQhP);x?g`T*4tf_^tlV!zFJ7aayJit3L70oJu=yVSc#5xEN`JU>%!3Q}R*$n6E0dp%@D-ZlwIWz|~v`AdF zluMUNzxbPEot}jkp7)7iZVAAXSwZ%tBY0btDxKfBKdQ2oL|pS=wtA+aZrJNQ`g6LK zgdDYvY&zM_v%29z?IpEuLzXu!^2yDUe4>q?gHxu)4LQp5+alf< zYE@%K32pGy{q91`EPOijcv2l_*!F1JqouzM9BKyo`ST zrmoNip1b!HAXsPmBO=SDU_6Z9z|ln^2_3t4ad3?c$bN);60K&U2gy*c$2Y|}D4ohp zW#BEK1LEU{4Lk4f%oHa)O6?k!lWzh$I{A8z6EaiMy7onU<92%?u`Jr;Wm=*}V>PI2 zKT??&6q7A3a>2^#2jm5%A2uIgBmGWo?%7p`h6XNM+JNc>(;Y=ky~Oss3~W>A<;Eoo zpBPyA*0G+ul0B~wpOD?w;6SkpOc2+h35O`OyCTDPk_<;WF#;zYhLp@c#`D)6rR>K9 z1|;77bA}RO&QLpUN6^7a(~n%8f(%;GQMA`X6Hs5mNtSUY$*_Ww!c%lqCbDd(01Hs1 zY1pT3m(Lkw(DqYnlDC;21yzu>pKy?A_e$l9JnTrD;DZQOe~jB&o)(m{RKM^Jyb)DY z4wYB_VYmq4#Sho>*w+uzdl;@4Z-k4MNQu!mvq)sBfn6#JNdu=h>#a`amdom@`S+WA zu2XScf<-UlSXanui!WNxCN`#ZJMV8&_L^?omh|O@Q2Vn4s$J@|o$he7`5l@>hz^iv z5KR~tN0McI)6}(j#5Xr*03|TBwpsH% zYC9W^vO*9){%+MFBaC&|g{UB+G z4gPw~qrQMbF+e3k&q~GVuNVM-WIALsyog{jTQIY=toqoS>j&c_OHDew>KZsA#BHs>9F4npap+=je-LK_p^p3*>Onuc1?A z5>#x#o7!r*cR$&OJ96(3hp`hzx(ZBlXeGWrY7|~xD7&e5&{_36N{9zd+qAQvoV0DB zHt8n&yJl%xg_>R&qs81$S=wjWtrW=yOsi5LwoWDvIfH0d7uQaSN18!-{O+H$=MP62 z%J+?xfPR*aRmBIMcab<=x;qMuuBdT)wyo`IReRoo$s{b0fnaOv5lt*H#bv7)K7?A7 zZvq`)dj~d{yLr@(;;UG$)IBEbL6ENH#q&&naxU4if@gFIyTM%cPQ8@wl;Wp$RJ**Z8G(8m45Ygz+`OO z{pHd8xw2<{M55;tu0F8Ahe1?@Y9L zZ26mwQZ8!*e*Al%-!l(3pfigcmU6c%(|$~Kkl-nl%&dlW7pvPjelKsPteUzDS5aKw z{Zi3xzk^!Y-5jSR0DNt$+G}EMzFtOY^oMO0nNNJ}LP}fazabch-DCt3PiycH=7>)c znqgdNqDekq~UjGunX(1agK(RaB>9!v7KH#g% z=>|**>)gpIU-0JAffGN^QpWg+#Z>KtO1yM80+Mmrap10y{G>dJ8OQCrV2W>E4BJv< z^G)`4)(`P4Za(6$fVA6(JtH+Vd2i6bsgn4e03VLFU&+9;V~~rzOPji($mUe?bOgpK z-~wN^D1!rTAUqJx=(HxPJSNhH?IKy}$fDHcG@Zl3y!#!w)ALw6xOc)CP41yi}e;LfIcWs3K3 zGV;6c)(0`M3EDz`X7E)QvccxSz`}}1rYiks>7kke9|DS7@`t7!s2$0bfS*FGukyZvTKu2(wVsNE&^lE>!LmA;B-05Q1^`5Nz#ZWXp|0+5%HaNLm-X$+VmlDP}%LC zmIl>QcclXkanSHuwQd^qLP)yKpXjxcj zWis($o3>tp#<{Mx`s-Jp%AGtcaRuzPvRd9+34w(yr@I$~M!vf_Si0OFYF8f?es5tU zhqI6wcJ(T-3Msp9xLi8ckHs*NTR$U`vrsY`k91)vEFL}D zR8fTTOfe2B7|ZP=#*_ON;h7CZzwh1ZePcK|9Lo{p8g}! znAO`jr6(KGKFvErh+}kHYw$QDHMT4#N4w<>7p>yCuC%mrk;(>wxYZ&mBO~AGBan{k z9Vc&*x%*ltXjA3&OJSciMd0Jdy~(6Ic?Opu>8Z038Sg+hUkJ&_^!~VS)8}J}47-=p zyTp6@wr))}w|oHc>>Bzu#mlm0-X&mPpKM@sgvGxwKhH@WKCoE#higAc=o_*H;Mww4 z9Z9$F)6d%9i*0GIFXfGY4j`8;rhH&@#%fTvOMGGl4nIlHO~Zf*m!kCyyui z7%$lvNwK`HToS81#6~?cuL^eTPMCMFn|Zi08ZP$W{VON$M%GOz@JV-`l{=-T183}UA(5yRJ)`uTZf zcdM<&vOMbQvAXtkGAx!)CZ`g0MDp>oKl)X{g3m6?QDwN~ve+NbG zSq1mcRX6QjTKH_8(IK>5)~UNUPvf3Tjt4%Jqr)Gt-~=%B548ArKfzf4OFu!%iAL+f z7i^3bO0LzDk};9+$bM5WLe@@7Z!i{?DDlw$gya`SHXhuX4RYd_nHlIR$}2-m#V+$a zhI<{_uEok?rrdYKVVR3F54v)PlIV^zij)etHf1+1viK|yjZkpuP+gI@u*i}S6#AW>#?r`k@ron6wGR7 zI_^`544ZcKJd4eL#>7$T!A|H;NI_DMx-zJovVTNsEbIeEI&Ffw>|USN*T{oUD0Qt=(Sb ziVfi8vgua^^-y}5l3?n$`S^%)Z}Jv140N%Khb@OSl{Q9x4u z+9G^PXEJ;kp;C2+mhZNdw}0^p%UF5SMIu&=rA^Ig^g%|#TXxQa^Q73&7G*RxmFsDv zzbiRRlJaiL@OD|~=K>l%r}o4q3jh$UKgfLoubd%9>DI&Rl}GJz%ig=|ZGny+ zriTX(ZKq@K%_hwowCjASl2R`XhX7@PaLXZ~@vIc`aCy^!jhWrJ?aKT$vj07Vs9mT3 zWEn1=m1~n~?BmS(Sza5&#^6>t5l)f_X#}m`A}Woi(S6}1@|T7#MNZp!LK5fx0_1j zTu79~7jq4!S;f^r07rfG%rxKa?mMBTi!=eS0RGA4Z9KULBT;A& z%8@Naqh>ROfZ^F-cCjkjfdBi<(p z<CXEMBu&^u?qUlORH-GF##$=wbU>M!7=(~VCJj1GIdAQ}`> zl!5F{O^s(1LcUk3dE(Kj@ta1uXHJP6{h&C zHsx|EgY#}=l6+)US0a@fQ@rXIr*bM?dCXoGKDq45o1NqRme2SqbR(%!sGtsfBw}88 zfhGy1Q^*xRO11Ek z^mO^?N+Kj>rk}I~OI+2(bRSY<0YCa%ajl4bp;JYl$}Kd7>tDAY->(%J_vC+ZojjC? zWclknJYFawx&HhJ5BtGS3LZCmPVb2yRo{FPw7)U)?t6aP3f#T8>fE9uzki zx6z$AnsK}P>7Qy$`RIvj@IS=|58g^*>He>fmBqLJH*u(-TQtLSBw0S=D%i}TdH0&{ z!UJ7&aw~t^5-oaHbF?3g)8<($>$fg3qz^U{wRyi}K}a5-#U3WNTe0*wZne`zbx`Ja zfUfQ76*yW?)6L&R@CjmVCBOrf+2ebnk?GD`P=R&db#g0gOktBW`|giSr2N`HO+JI$ z(YE*PCi&_eh+pp0=U~w5WA6N+` zkQu3A2wks4m$Z-kL#kuEm4wxlnebtHyi$_HIQ5dy!$U47pSrpbS!hP>DI0z=X;E3) zME8tZ^UwEfrf_xkBbm*ZU*&aX-ZKPYo&sJ0LTKNTl#n~q#xD`p!?pR4l3o1q`MnQ& zxNRSq!U7iK)yZaSXEX_sglaAh%@k&X^1E@tftcGB+18v@;MNdI)}r~tuIciGYE z1`~@$!_w0Q-~D*;55TE3C{-22N1*3;UjdWJy|bfkwvJ9@_^Ic8d8j<;&eh6n$B4AX`wxl43Gpwc z%0-_VyB;^H$*x~dQO(xZ0sCRDGurCm@a2J9!%w@%SbV{S@j3I0syHCXcaw2aWW6Zv zQ)OB}J!|?!+C}RLe@yVD@WoKgT`I0%YBVd+v&OJqL2i$C2$y*VwkP%?CwfJ>fjl_4 zEOx_NRq&wPj5acEFBOrHq}iXNvH@Roh~Um-Nze(t0rTlt_{Y-jC;2+1F~@h4GS62YjXx^ zGTAw1OhWUk^CO*n-&>~?r^FZa?%F6iFxll<5Zm*guI+w%n%|NeUCdpW)$Zy)G%oLS z{W$;Scs~_Skb7A<{iauYsD9R z`CLJ;XMY-)iJasTc^nCcvDxH84*-~S;RB=F%!e5A65C58-@B!mU*_$K3^qbqt8U3-#;Lz$uh-iY<&aKmRhsYSUTo zsjIj%-$#_=9ZJ)l2JTr3s%l=?KI%u>&a}kKQyS~W3-gEo<2BaIw}2G>pN{@*EeC&j z{E_JjQl8B}S8Orvsh&UUQA*|~R7XCfov3zsKIHo?LD?}aDs68L9VgSVB+!mfnI#Ka zy2J8SO6|35E%2ew-@tK)Eb+q{*DvLPQ+2Y4jIxr3dv`_vZ;hS29aX(GM_p0Y!U)#z zli~AIY&jb>_~qQL`*2_;bJU>KiyFe?#tT1XS&L8%1HtmbAw`XMR)&Pn8o}ju@Wx~W zqS?e}L zlEqiKH(ua}1$!D?jB7fO9C*5{JLi@KTnrW|I*Ns>y_MUq&5icgE|_M4yfMv~jH=;m zG=;Tn#y*+WuR@XH_s}Dz_Pk<(Bg$=&^EkAC-K7!B)jH|oF3NVk_UqRzu#NhK-Og5d zy*6w)8UR}m$jt&~;ghlKNnvA|>+UVl7o4Pk9;=O!DxSz~J4u*l!*J{vTZs-ZORUwp zptU2~LrW(DzK*)yvlI+B^iB=lJr`zNaqVmg6q@05yE~|^RXMSV>#>&cgl+NJ@%4(( za};R9nA&klhc?j06pXIT!EY}{-uB%WVCSAXU4{Kt6KJQwhL8LrHJ^jkI8V7avE$_A zM&pXZyv`lY4p##EXmeSN}cwW1AYT}vrUjuJBmj}x+LHh@!-5mC_k6*mJc z4J4hP=&M*O(X-}ApQ)YkIu{KIexB>n{__>Nt0I7@NWB*lgiqOLY)TIs`rKs#aqZiQa;De{8t3$s3Uhig~$U}f>O|TAzr-K`k0!FBr znZ%>OYplGN<2l;S&I1C9yJUo_ds6ZBRN(Y@eVy0w#%(t{rRO9fo}}_XudC`BqYnou zDI{VDlC(AQxNO1w@xklU^vcR@1%US@CmTR?vZ(DDzSknQ)6U01L}hScP8cFjC=1wa zs(R$EskQG%AIprPSF4q;Pd$Wj+4Doz?d|YOdOQX|pJ1S@jTcnn`{(1@4E2h4jLx#@ z{?55@*v?I5tw3r^UcmE!ujOK)rM6jjtRB!spdrh~HJWGCsgR+XcXGjd4PsEPpfuWy zs@-PwzR?SuZw!D2XRp@V)nIJ2;2E_2s_f$ZzkXh*BO@tV{ z*2$KQ;QoLS)=2)VCl-x4H8FC)0k#Z(yD%}@5+kMLXrf?>i!XwdujH7$PKf>ui;2tr zfkbDTRq4<_w%wH4MMYki%6<18Y2D%gzDkc0v0Lx*$|2X{m>e95rD}gw2|qAoL}1Ry z5z_H76=kSpl|uLwZbPdX*%^+4yQ9v|e)wygXYlf-Uu~}bKn=A5gt)PMt_qXusX5fd zR;n#4Bk4-GPPq(MiI@U6b;!h-U-DUTTirIOiUcQaFdJ)&-aAHVm?edW+X8pGTlf(r zKK{;5@I*~0u?_R9!J|-Cp$ZjaX^oaQtm{sDt>I^H@SSywyQa>vSJb&q@4l+1A24CK zygu=B;{~n#7tI~qsz7ofq!|v02}h@dujEgs2F)58;-(bkMd>b79UHctcd*Mo@9T?^U2d%?mvr%bW5|}aPbOk zDUWtcgW>p}gJaZ@wNn8=U5uZprj72+i1D-=_jlPMue_-r$|K`i=)ZnMXsI3p-A>%C zw>B{$)xE3cKP{~pNxd*Ttj>&WgT!}o_oQKi!U4ym>LFdMYU0!miS%`Ay3)R}vP3xC z;nbqhV1A&-^nHOX{8MzboofkOtmyr@jNH(4)UoCtHE8dbFEi6h)a`*yWS!sR($u8n zfLH;iUtC+xYJrC^Au&Jl(H0OvYEsQn>CqBFTi}Z871rrW{}1KoH7?jzm`Jg=Szq_m zV#o2BKq{5LncZ)LmX2{0r^^`YO-R6E#0W7kmu8hxcRs(oj0zuOW8k&U!l3vpGx(JY zU8)51dMjqo%RtLs4Hw^8pp;CjsraJcMY+eSW#!PAYdXDwAebxnOo@~-ZMfoK$5y@Z z$4~*n1<@mv75ikytVWh)Lup$dwRrv!u;whF+o)!VZ1kQ!yHD9H&{qaL0oC#FsWPa! zJJ|FfUM(4+^s|=q^fYV6=mBDLZ@bhGK5GbAOPKi0q0@%a?l^-+16d%bWG7xt zy=P!#!_V6Ggc0?9qh)OS2jinXXMPqDR#mPbIfW~(_CIlW{8M}5F?q5oWy&|jTTYJ? zIn@AzLx~uJ=}*c03ejWx*=%B{AiBor3*pW5_{__fsy+RwcJH10PB4Ldm7WNbrs}^LnA|p4q{iE5}taDh%k3yUBRmHZ6gS0P41J?c72{a zXH%EM6Sa0V*fdB^$O-sb_FbhPMF?UmxYQH)t_@{_iXV|GGi-B11&W5B(uFe#Rp zl}+^frbcYBh zxAy*q(wxL)z9OsJ>DM*L=hT_oC2XtdO=SHoO%)61%;3k(S`68kJ@zJlBLHZ@GIz1v zF)_11_7&3(AKPgYLDJeEm8^bA|GLpZ9jQw$ro_U&bZ$QG+1JN#<04>xq+Qjl)Jk{V zK-3QGH*>E<`wh{KK3Sa*?}>u9YAM=OI|iydX4oHOZ9xUU#t5?7FNWj(w^;IUFd6O`=#?iRaV z{Jd6@O30AT)W}++_iOtFrTOFR>rbne{S!-~ba!zzr@3BU)vrfQTpF|AGofE*@M2nd z&=lqUhznNodMqlq9OOkV2|I(Zwg!ExrCnif+X|%1*Tl^BL7U%cDt_(Vw{U zR-ES#VS)z7O7UtUXB#;6Vx9Ots-&T+Tn#l3bxwtq&utS|Xr8K%OsXtW04kG@_5 z{rg$9n@(}8$f1$J==+7j6*v^q2-*5pi8eS@2J)1FG*hJqH{@`G;*&Kmjw*i}Wntnvqq*Uhtap&F*CQ%JA^;O!iPp8jtiq5V^w9Q4__H56?>yJh`tK4h5CA)&Q#nS_7+*Eya# zGwiZ(>}yL}3{zYJdTVR*W!3T1f4^eLIJLmb!^lQUR~09ihd=}4GE)`h@<570jRqr# z(+w9)^z-cz|G&#vx%t#6T$Pd!lz>gtDfwzx?_i9osyDlO#tv~kraP$`359kcZ+3-6 z+tbAV4t!#s&zwwg#2W~6jOQorbOh`SkNb~$9bi2SUie>7^!tD>|HrP9`dmT~dHpTJ z`tOk+e5OWio*b|zBqpH~UH$_a-(tseCPtqB_5xu-v;Q;f`u}GBa0SIFTAqr^-~VXv z(<)TAhL9lE-k}8T`2s%FojVcKu_6%^dF!dZxw-i)M0Tkeb$OEi?*jZ|(1}-I(Mo%-rIr8< zht2se4>TYnWA^ru=q=a3Q1A}16*K_t;p`mpBUIFXEw>m05}p{G$Tn_o>nS1qi!3hd zgsRos+uLYhXoxvaDYNY^fz=qFjI7CjNl=Xmk4n(o#zr@=t!=1swQCESPJX%CmBLfv z=j+@1gA$f&qYlukarcA!-w6u~^ExahrKIp4p|GTSd&PwQmEudtU=q6C26hoLI{9-Y z3htk3(6adJ*J@0V^e36^M@~ohw9>_cl#~=A<(`3o0b*c`QTOS-`x=MbbbZaxu$cfq zaVTBHYNTe1{h{cel)`Rv9b-|!e?I&mZc2bGfM}de{+A0NpU4&zNfG`d)N!)Tf$;+_ zhR7#`nPZj5hCUbNdW|ltU$KBwKR-OmkDhC|OmBAQ;7RU8k}QT;Pi_t?U~$z98n@zs z_NF04rt6!VTHX*Ei9mBpOI$MkkFdHjGpWc`mqv*|T-s~~QDrB18<)viH)cInqsDGK z69GjP1qJnXs6&sVM@FsQt)3?YRFTp^R=qj}8HE%gyS@ zLkJo67pu%VFHhXv&z+W9WP!LB7xzcY!>N28LkYtoO&)g3i*%xFhb6SX_v2@DZS@9v zVL{L5VxK4s$gExd@@c@#jAqiQT)e_)nn)jD21?4+LhW5))S9mh_gA>WfV2Z1{;IZ+ z_w(~htkBVIJcX<6<;f@Fk#TztZVV){8NSIbn#@$h+mjIMxnq2}ywj;7bquP54$Ee?!*M-d(QykSx0Cez{MOJ0=d3Im;45NcL3d~p z2D(dB0e$7T+!7Lef4ROr$6?kRK^hwqb33g+UL$>!o11%sI*d0OUTBg7dNyb<(PejZ z;JGxmG?lTs7FRcV$;s`G(MWJ|ak}p><~e#g5o3CVz<**ybjbLp(Z1B;;;`s%oRNhvTu0ZiD z6-_0eY1Q1^T=(4E_t7ms(EjhedK|J3tp%@)PBJW81edW~wda_b@$f(tQ~4+bd_B9a zL8|!C3SOiCz*SqkT$h&Eq3K*gf`Yak9e)&`V(3SOsdiQv9Zt>@`s0TNgxCM}(s{j) zRj>AVf1XQ07JYwr2yd?UyWz#di#&kUEx=&fWqOK58cof{o+oQq_#*yi*4@V@HCDsE z=;h2{G67ye3=$e?b$fZDKzo66pvy8-q+am#>o*J{XL@#$>u*%#)D*V|3Y&zziG&(o z{jwjH8f?_=eQ@aiYw1qh(eY6GkTP|t)u%q}@DM}XI9nECd3}9(CRTIYc)2_U`pM~O z3tSAMQ91J(IZk`z0IPcz(3!88qE&9th=F8dSR~?cxF6jWBqCCAM*U7@dO;F}jiCUn z%1;P?x==MI&L4FE^VwecRd=wEDd00QioT-;Q>bfeGh~x;SuVDL>=w>;w1q1k`#w!; z|M+D$#{cf7-5BC!pV$5vpWV0cyV!YgE}yi`w^~qc8-&Dw{)(9c~xFaAmB!nirS24wa|7d1xnTCst>;GfzKckx3x;9`~j|Wi@5D*X) zk={Xihogqxq<4_sK}zTZMd?jS=tb!rq<2Jm4L$VULk|!jki7dG&;8uv8{_$YJnwiJ z{*ma;UTe)Y*PPe9uDL{;y1M_cT;E?advCMjfic{jN>H%W*Ke|u$>=t7X4TrR&(e8fz)1i zA8L0U%5?uE1UX0(?;ajnp-{bEI$TxkbUU{$?Le1{#%61)CAY1iN1n@JeEgnEEtJ(( z#KfxFiG!QGMPkG!SAWp4ad0ru0m^lrb3mfQWz+=d<{80=y+~@Ik)reQAlX6V)t zL+w&B7pT>U$x4q?0u|fY4e79sz&ZH21QSCwF>O_4*~L`Ur1Ts*B}g#jv&?iIwF2{1)(OXeO3gm3>i%P7Vu2<{_>^Gx&c7R+(@cH5Gn04!IHnhYM(U zA-9J4tW}O?tC^Vu%OhfA%gU7H<>kq=wIhi;Lx7)lU-V&!+x`1Elkf@i@$;Ujw9482 zk3TC4_=E$pC`Ly|UuNfa<<2zd(usa}k6o4+EsOeY3LKd*LBPfN05kGf&B0-4SEC>_ zwDDfHKl);Pe4LSy@zbZfLgM0~at6&@)pG9cXRUyAda*SP8hc(n^*b8+*{-Kmj&1k3 zqGM*Z?zq7Li}WD2DPaB zQ%S$Bm5zHswr(I$*LrWv^~FK6)9rm4nyiL~nQChor(wgWPdFIl1#%`O&1e$+j7wzk zLw9S7{9qpN`@ni0TX?ID#hSSul^X$KZ+HOu!V&0`K}W~SbAr$~1iE-g_?*Rk{rZxQ z+QKD8`#|PC&m<(26nePSO20*X2WYwRVf4KY{2p}oN2gN=A<#Er z?<~dI*tk>n5jQ8Ng!h^-pL}a{j~Q-A*OxEe$Zd)zPrRg1Dk=)67Z-I^sRs<~sVV1LTffk^mf{Vp2s{cel6C(#XJ2RjLIv zJ|1~<<(B{Uw-^0ZSFC`^ijB3kH?N-Sw!Ate17__JKEC6(0#y(X&zQMPlq+D6{=Ly% zU0s`lNk+l}DShL5XIs9;uK9~q_Hfdk}wC@UyO-)Vx zPTTQJ$cc@U6PlRlaf`lt*I-@*3+#*MDtXFEIrx0cc%>bZK@U_|jNVPb-(uihCOFWnA62hNg1de5OF zD!_qwG*@e{>orqTr19qM+Z1`1A3XA5VS|Zcn;RCxKWdd#6zH-6ZDzTL%a07cq~7&b z$nEuHQ9QILFCB2y!d!08dEHr5wFP;3&48do$a#q&`^3C=ZgyTZl|Kcx9dLndG2JSi znModK`PUKNffQ_+N4hr)HJZDX>SzD(I#nQ3dBx9ra_+6m3BDmVsB@Zn2TukzJh8l@ zVwR*^o#mjma@y0I4;>1k-lqvoO)^-Fe*j}&L{i16tDCZtkB&~s?}b?*8t7MGri)^_ zo~|%dz>5egd?kiOvK}QFIBU`B2VF@aZ?FsqTQV*>rlg92b1W7gP@(Qo?FBnNs^+cM z)YRnX7ohvqS;F2B9_|VlG_Y93>@R;mdy?r!9fOg<4+|~G;~)2by-+f0Q}L6AODo6D z5!3FPhuoXuIy{8u=H*SOYnZe`T0No^!8odlitwTmBcrkZSk6EcOz!$gnb|kW1G2s~ zId>!8nz3(nByl7s&Yd(|k_HJ-*igRNw^_FXmd)V3AiXQtv|*Iraid|nw)SFLj9`-> zL=|eFZjTITSIr96)4$o(zWFO@Bm?9AFW&g=et&U)$y1xQ1xQ+`CY7y1zl-XH>uOTM z#Ujs-97m}mFg#T5O`M~Ld(VVc68+&-k>J?g4=ale`hc|nU!>7|O8$K-$BO7hqvRBm z&BV#M|0Fyss0*(ov8#5M zgcO|uL8K>5V~ImyH1a-w-Tnuc9qrZOKeYZ^Yfe2;yb77;q^A?q8FxoEI4KUd!i}K` z@rO+oHW`Ucpf0T~OX<8^6c(B{*H=CgY1Mg*jRWF1M$iPJyaA3(s>iJY-#dIbfl(#Jb74~8mMcl5*b(ZXPzJ3_^VRpbmj}K512I%)?3p%0moyaSZ)ZHYgScEjKD^Hj+*Q$|FmYiwN1_h)FnBn>3AccoU-l*2>8* z|AFo57Ni!%Vv1K$HcJB^u2MPMUs%s$%=PC)+h6={!Sz=lCl9;DeCbz5jin0cSBv&J zU>TPhCEwX=!%u%L(Dqt&wGwKK>m0SZJR&}cP;gRmbrkBHydI`PPE;@NHyWfH=yI)? z_u_-2sD$clOg5RcZm$9eI2~~dz(VE5eqP&KD2=H}fd<2r6+fkcwmbE`O=j?V6Q8QEJTt z!$$!lz1VajWFreZ)=S5lF8jNdgBBSQc+mrILKU1KoJF71xWA5%56fKno}&2AA*bKM zql&eqgK%_4GH##`#4{Hvgy@Aw16t!doy*TmHn(acfKRR`%6{9!WlXUdMhbEoxnAze zDH9_GzWg}F|ExXcD4t|(aAdU609MPsUqbFTll<@$Pa#fS9XMf6uWoX1J$ga1kH?}v zGl$8k$$L-5U1?7^l0g%Q_Gg|vIo5lt=({#KI|l~4xmHye3Ey5oiHHT9ErtC@;1Sz+ z;R+trOa%r0)OtVkBBpbgl(gSzDk#fK?lp-?3Z}9;&v*2>4te2t2LWo4PP7LDV;9j= zGm-awuLRRNp|PfRs!E~gB7WnR*IV>^dplK(dHnqR_;`4PhqI}fsdV}3Q=(L)1w)f# zWhR=M?k8tIP|n7WiTT?3lYDzSje>jam&aJxcpc#R0@-Y}MjJDQE_|8kH=i=nd{Qqe zN;Hnzwxj0Z++r2Wkga5c58tG!A2Kk^B#k_0&i-6bZYb)uQ0dQ1rd5mU>9o*(K+EPz z#==&j3rhytB1j0PQ9nQ4Jp1uEW!DzOFc|+#%2t1Zyew>Ib9X@9Zq*93_>r^XRBZ4+p>QJR(*f+ z1iGKtxX|vuh!|_NGt~QM0Y6F=hF@Xp&e`Q(e*OBDg@r|Td;hP%s!me%YVtC3b2_)G z>f!|sN9x7llBA@BC-u9d-aUS3G7mw3RCW!D&dr^-MfE5flo~misH-c1NE|L&x>dGS zsZadT3boO}x2FQ~4^PI_h%s4y+p1Z8pn33RK2 zh+UV7taY8Q*3!)5NbC|1Ap`USi$6@ERpE2vQ_tc_NzJn9ldohWtL>%-j?czETgNnp zRk*+s!Jrzy;Y7g$QR=y733k5qkSHak$mRViB^6`SgF62#$rk0v7<6|nIhDvX8^g}v z1p#|l_ugnxNwkv$6E;g2tZnByPM5|yZg}_{y;$G9&X%yskKS5AeQ ztUZ5z$tb~@r!{|ZH%sbpwn{s(*PzZy@x%L{1t{mx!X#U4&#-=}hvC<(Bq7rQrA`lO zW3)JFu)4NdwL#nUbnPGvOD$CSd#hovBEAsG&JzuP0AUj zGc74VIiu`*o{`|T-{JY!6a~=zs5FX=ZFHNzG^nUQY)SR-+4-w5NiaxrgR4ivuex{W7yMxB8*YR7psz$^RBXLiC8GSb5prAjY zi3yL#dWoEwVCl?EZ|;5WVF0-D?pdLLD$=jz1$cJ}IiB)h^^w}DsoLsysPlM;X9ZjQ z4XN6Pk5a^&7S__iK|9kE75W&d8NZD?)uuz+xm}l=fHie(BgqmHHaEyztE!h;&aCpQ zMA8W}nun{XSRWtbpCSb-JZ?;nH@d!5uKY!ZM|g%pUzTg7U8vG5oj`8D%tM321eZ5O z<$te@(B2sOI?v6!5eVi^N874gH1`S(lr#JhqH(`jS%r?pl9((OLrTie`J9AD%X)QR zhp)7WL+DwDme_N?y)=3Ky2xQ9B|d`_=$liV8jn1X`Mkf+!AWhzGp4CICF;IAJzlv8 zpLVr;0@Vzala}TbWU4wXyVjHP!?ZUvfa2&6jiT9#?ZEu}@B`tWe$Wj$f6Q6i{v#2Q zSu##$b*Bs1uqvpVkugqP%Wu^p2!=Hg_V03?{4)fK*xcCo_4dt3rf_n4a$#<+y1Kfd zM?)74$#FXYV{%%2PGK$x1e{`t=1gqtC6&4y0^q1-p$Z;8mXgBF@ST$W3CA4z&a_&G z+smbcECY$(dpw|i4~7-<;DMkALQI%w?13Y(vYQ3=?9dNVWE;TOdOr%71zO3_FMk?b zrZ6*SK^aeZ!9M!M>FI&TB`qy)Wb{*$`)rF?jbjdZRO_(xDn59sD#m^#n9`cbgyg=y zT6Vj=s5{-=-Rk2eZocG*B;!YV-XgQJ%tS}lcF$i;y6&4ycshFY56NwRU=WFmgG%B2 zjJuqEpP6n5vUxzPoGAkDMV#dL)`!}(oGYz9+O?&tKUaery}pYXLDZvO?PAYXGuSF9 z{u#}U^%WXTBX;_Ey9yh+r;3d9MFA!d<6Cembp<&=QcH|Asl{6vMfzrlVAi8;=31cH zRd^AMJU@r%#Mm{42(~+3n^<^@cV1+K%4sRL8o(qaVJ{-WZceWzRE&Hlr;21jsdM0@ z@+B6=Va9BL*GEN(Qio5{WotXm!D>xt4RdwR7V##wIe2%aE<;K*aF%tb$e%NCb~-LM zvJ?0Boo;a&e}|8Lqq2{Tek8PKO4ngE*w4;yJ6**aVPj(pGj6D{MQUr6#CFFeo429c2qwK z&^m~u*VI_h#l5da?C#=QU!3@ezu$RP9{K2pZekAeBYqmL^n}DXbwkaKCO2f?Nqo&- zcysLUBEpI<=AWN{CNi>;Ed+KiRX^@It5pN0%BjKR@q<4d#oU+bmPDkuQ6VmGKHp=~ zg*hyZzhdRV{2UopqUC$qcKkU8zK&!jN=i)FU)VT>PtL~Y&u?sP8B2PKi_$46Z6xG& znU^=`&(5*3vTtu#m^6C@Q=%mVnfA`qgbc)Fad5g5HgeZ-Q4c7>9uaLKufz;hA4h0; z+yn@K333iw0Y{>hZ#^J^ZFg*S1N@WO7Pd|O)5mt->cKA7YGz#+3n%BfkGm8d$CrUf ztSYD#O~^pE-R%a*Dx{^!qp{BB+q(Mtap}o@3mP8|#v3W!C=Mjundrp%)g5Rc21WV9 z1oL2F$OlhLD=zen6!GvsA(e?lfZb5;u7=g{I#SV`jy}5C-=7NG_1%A+Np-mi^&q0# z=VAk5^X}v2iu{R7*?djb_KK$FJFm6TrL)N=bfUfsj{7DWXhL4t;BadI;`$3~H81aY zmX!DLWm`c@;97B1b8h3pH}0$$=?*XJjgtZo)&lo>GtK{H_dZXMp3h`qpq2jV)Ge zjyCGK5dfbo*e=I>yrkjr80Xj1YwSeVVRwUnpCET)XAIl)kFeH1L@Cd`R&RAD&juK< z0=W$hg>&Y6djej5%Sfp-z+1Oo6C@WPen*%qCgs3?p?HuulxCc9H{esg$08%U&|~5( z7oYwdjlkKk>u>Y14zx{tONR1%Nt`?QYcQBiN{x7t3qt~ha{;m~l zXd%sonIy}w&BhTg^(X4wS2TI~`&zsMl z`mSh3X)_y>McZrL1{)R3$qn{nU!8uT->%iK^Y`BW8L?h|3g%ZjNFK}fq)uG< z@ZwxGKwtiy3}DNB92uzS|l`QF51}}w6|3icm0&o z6d=cqJQov4tDhT{sbJx*Un~qWVuEQ-PRkSGc~ydyFY&qQ?8dE+XYMh7xr-v;SHZ)) z0g*gcQJt4A8k6BYKj`aoEqf%F2=t@3r-#&76@2yHNJxjHZE3HyctTxSZHfr8+ zU&RZa_dKkgkBWCh?jTEvdsl{e#C2ue_+{}jG zcFehd50?2NNMzQ`N@Kc+xuSg6ZSwr2JPLH?juni~eL_4X;K1BrCACl|d5lq}^YM6( zJMrdkd-#Z@7jV7JqGx2RC@P!&`BzC0Z59lsA}@E0b+^S#z5)`sJqc$Q*AG9Nk<1E; z;b}zAMco&pXNZo<#YWiK`e*_+0>h2((S@VW4##hblD1TD_q|&kHeOU8_{?zlxE&_< zR$T!@i(K-JWId|408^CgLWCA+4h$NF}uE4b{YK^@=ynZtAleFl2(vO0Zc6k-&?U9Ng8AECy-V@2VZ?xzbHZZ zve)KyxfW(Wt+x;%5!Oy+hK66EMc>Mh@E?O5W{bLQFK@c50aGOii6Z988_Vqu5}E!% zW1PmJTRc_@O+K{~DVL62>+fePk?TJRm6Lg`25cdEdV0Gp!2DVwBgsDp*HMeSZgoM% z1qKF|D$yz65x%5b->nB3C>qw#zA7^Qr+|4mY`1aU?ld3m0h1(- z{p+Pyi@gTKN0j(#@q_bdEd?bQCF1(>6e`4L-K<860X-=jw7F+Lo&+T8J+>^(ohp{o7FE+i{BXiR!851E79f_Fu_K5 z?TWIJQF=nmQ|q2CtfimW3o`F3E_@uDz){gqd3-Rt4kJ1&4^z2QNLwa)A>1&A@tkHU z$yNa6bq8$@7!Xm@veLWRL*E8sncJToM){sQin+ENLEVNX;RQqm!69uTzQ4Zdm<%%w zleGJhXc=?%*0OZg9XiihKSp|Qo%e#yyx>e*rx=t19v;_>?zusg-A)rV2RS>lz-D4~ zYy0;343V=_x#7apT(F2x?BmO;)0^G?j=MwZ)z02pZG8V6Ntgtxek|#|+aqVAPHrxh zhxj9rQCva-nCgn->Ok$qn<00S2caz7oY2rGwcu_Lun`kAH0lGW0nw_wJe_)ZK~_>C zTmR-(UOo@yfwNb`MV0#b8&q-!Ql5p*75s}06o2jE=8-fI!Qy8ZLSQA)$yc?c=!?ccwg2(u_C5n z3Xv4?uq1MFV*@i^$FMT}&K~L>UGP(}U1V8_$)VTH5ZfO&l#YXuH>mmCFStPLY$Isj z@8`(pny&5EDLW6h?CvFrEv>Tic=H@d`*#0?U7_|lJe%P@go&;^kd9co)fak|gM4r< z29EICG>XfjIlqveOrtoEQU0o?PX6GMN?E__x@}lh6$KzX?y>QKRz|CI-(fE{^9oKB z6(Dtvf4ieQ?HW-V*yZ)2B82B|ey%}QXez-|b$!jJ$W=!frO9S|=4W6b$|eulo$8Q- z9$n}YvMb}(mrNregVw$?GvL%$jGVkJYN{HHoEdL(?tlI37&E>L92n<%`{^0U@5RlX zTC$E(cGr`o@pyTK2~unLs~NJ-b_#Wu>wEYpYG?#bW;-${U3h>)oY<0?ang_G&J7!D zxzg?Z;qvFpCuxXbMa5e`gk1@3Cz5ykbX+~M)Y=*(`^3T$a@w#kVKw%0`@BNsMKQcX zPF@x@R$kl^{7pX^VW+3@dFi&NIfEczm-=v>k#o>qz#U}v(L~$NK`KNmgBf;)Is-gz z;aE+Oo&POGuVG1^%-^%|ad}H<6Pr405H;fxdgah)%T3%UHe=NVx>{~K{NZOxfzac` zHOT*hla(UM#0jJ}=>_PzDhA!Mkmxx0s1gAYq`{w_&k4Ioppw_!4g7Y6jYT@Z%ilLD z=L4~Gy+mhyt%V)-!7wHiF-7!S@rrjxjAg(_Rl=b26&J{=?>7h>Ssw7pcoIw4Wyz0;fv|g<(2eY(9!4S5|8|U z;>8uB|KG%fS*zLDjoN3}h{F#{^D|&p6CL%U0L9oNtu6AaeWT%@`2M4bS}n~*`|dRs z7N=2`V{M@X0#gYwX15Gc`PGa3#Nt3j^`A#iR{VR5#IeZ*_b_%UjoVJZ+$ zz*w1&-uNV+VQ;m3(K3DPEO_mEyFxzKk~MDineFY20ici(BcUUaUw%uQ9{B~kKbH+{ z^|U7(D7cJnBRVWCyn$N9#s^_&diwx$ZxW95+cF5kDd|4Pt*{<;yDXB)i}P}5!O>e)qsIAP$4P=_K6ZOoq# z-lG>0IavsMOZ>f~{l%Vd^TNne@R1Q|Y{}4&Sxqk#zqUwy;;xnI3$Mh4gvoa|0b$4j z!q#Jmdim(Q&>IDP{Ykpp`+8o+?S`EP#f)tG#yvD57IrGN`*JadzCMN`I`jupTq(J&>iM9^Cj*^0cGC?;rr z@`Owp_x_#2&0;BR)+^s2EP5M39yR}7ina^u4||M5))9Wz>aUnhJf~o@(Fq+U_(or*j%xm1`^3%edNbwTxy}6X_$)AMhgZ;dS6AL> z4~Ni*uyWTwaisH1Y(KtpQn_e5K#-EI6*KDVk&uvxi(J_eq1i1gyd6c|y)iX1<=-$x z3L(1DZL7w<<9u}E&hI~LUlk1d#w2oz`%j+VrcqcbdbysGIMfxs1S(8G!|S0wxsoF7 zX|82Y?)8}Gyi<8w9=Xg!PQHei&Z_`y2l*C#@2qajzWwCdaD??UPinIP1VSL;y<1Oe z+J&9-hr^9kumP%CmxE5f(jA)K@+yoRQ> zFT!8-=XTQR6^zD^R7G8V>M5^Bez3>w+FG_)QVfot-)j&F$$nd+Hs?HLwa9+qDEA?= zC&kt_Nvw;B;yR?0A+KQxwb;npvgH`LX8ud%$lxt#_)(P7a4&M>iF*8c#q;^t#OJUs z9r&~WC9jHn-bfM=cX{UA@ODzTZ9!9h`E0{1m>&V$8{uOtN^-UJ+tMF zg8IU6H7?0IU09(nmY7Pvi6lmBX(of6jUdayI6W9#T;CoZLw_Z+7WGr4?*JAz!x097MG>km)s$t$xRzi5>RDn&OA%nDr#3P^Z9*W zVZXHO7k_MbL|qJR2P+exld)vvJ0;em>cPyYot{}$=aw!{XB4D!{uwGMA>k3xX|p%x zFNiT0vEHy=o>s+OVi$(I+a<|nAJ?R0N48?$l*GZlftaegZKPu8&R&1(FKGZ9fUlzm z4eLHIFs9Y>FVvu4h0v3coOQ1ch#)AD7Mot5ee2edS3oUhZpfs#G@FEs^2cm955Mro zP*F;-N$V9N>>k;as8#D6Gb2O-BCDD%YL-r>nuxmIL~`0ET3TC@5Jz-ZWr_pd` z0a5$XgPi5c6SIPI9|9^XYwLrBhB%94^9X#xylyUpeFb_VfKHUOqm;!==-mB~Cg~mwx1W zh!C(3ecg`|n}R)>qh$v7t*!&E{{m5qd8V1SzmeABq?L3!aBV)We9r>~4gpvFdZP+c z^W}POpkLjWYOR@80Dq2)h0Zs+F!I4NJGX&?LD$)<9H9O|Njban(>dS{J45j}9y|f$ zFj1vnYkO4Xy&QKn@rPsp1F>&KA+@|FeN+=F)2Uf5b+9a_e6wbzrx!s?Y-?jj)9#)Y zy0J;7!pAxfu=cFDk0mZ$Veq)$dXIFgiv`pg@&Z(4>uLD!A)Gra&B~majrY!9Wje!G0T3q@KljUz#M6KaR93$6kdFf3|M%6u(3q)sUu{;F zBIWAk;^PjnK4! zJEFpJ%8SIj&T4YRk_wo5YI%4Ccqv_xH?OVY?5G{#Q66z|aq$$T_VyOn)9CU-8HGv_ zQipUWV|V2e9S~=nKiZ0$>aH4QWj#4mmBZ~vCqLZmlQnA(bFp&K(UF}u zh17AaCM706qJ+bK?TwF>DdC?#tKYM>-E49ht0&x)6Lg%~?bGfBaF=L_`}!CG)X(4` zPy#fwsslnttX$*527ke*b-qnh;cG0Cz1%SMz`l7{k%?HXgm7`*okyg`+r>#myQ0H< zxOYC?b6yVgY@gXxIF23F1bEHWrvA2?+y;lj`^x&vJv!dpQMQ@?5i!+ww^3v^LZ=ilJ#p4n(7Pt05o(iqKxb>aD`5bKz<-_s(I3rw zLBG8jS{}97+xsbQ420F$s%e-ZwC*~Y8#UKzJB9=F5mBnR&_8q+Bn~Fdiyy)B4hf>OJW0gHDvcf z*k!X}-f0UZ)afv@1600rqn>|_&#;tmYg^yrRNPV~)w2DDE%1)WfI_uWverLy%4CT) znLK3^U}WVGekCN!$sMwNnJRySuk?PZ(Bj$YHqosx>#Hbzz=oxsu8m^;TR471Js~j{Y>VCLa<5Z9_ys>geilh~#-JmQT8?U3=>J9sI z5E6Fs%TuAY*&>hFr74!6O(x>t-M z{T>5Pxpb^hv2OXd!$4e_F6z268GEnJV^EX|yj*2|QX-^;~F@UqV7lT6xiR!z()10-zKXx~fH0d`JsV6%jq1e;X}&ex{)jmps83>B}t% zC^aCMOUTmMiIV(m^9%PqgtW|;@bE`>-XXNGw^-SF?!UoEp8gTj^%EYxM79#!$Fb26 z^G^T*aOF=oFd%nzd>U)Ioe4^KO5t*Fwlp4R_UR+dUZX zqmtgClprEWqA!40$p7jxJGX&FiW`1ZR{u)2>}%%hi1hu)pD`7oEIeGN$J2R#+|3Hr z_uSh=ZRy#mKPL{txy;XF;J3LJ&i3d^ z;`;DPs{B}tuCDO! zz-kq{82!1R)t~-FJHZPeM3^v}uZj;3$Cr>Of6z|&>e`zIl#}rTDbA7C0YWf;rt=)XBE)mhu?=#M^DtrdgpHwCUCo{ilIC$Z z4RrU(@u)6KPLBc|wZ5^eXCTUu)uQ{d)i7UGdi43%sPD1(pwb)ygl zw_f=wi*im%#H=$lz`0vO3%|X@=A(mN%yu|-{dc=IqxO6^ewHt!?`Qw|h3nad!MU7O zcpKPO>S=6fs0ol-T3;;LjuyIDHvNe6JqmD?y?&9!y&|Vzw+l#|XKh*KLr~7vaeiu> zWF*zf?1mb&ndvR-d&9UMPHYA<^@mWadz)L%lMS<8CA+dj`^6T_ckWC| zPWjztg`T=rC);0=kT?K&QV&eOuGg|WyDBw2b*n|o1pC-cSpECmqcFK}_6gXyfC6plALQ74s*7XKWAz^51@K+5HxtRwmnjrkeKi)N=H-enXs$Ai6VQxxRjLa zYoM{M&`GWLa#`RLoqXdQ@+8&$CuA*!uS`@{X;hVy5V$yuQ!VKgD8dJS-UQwl;#fkf zP%a6Kc4^^z#+Ly?0oRv0lE!2z14Df*Xe}cRb|$v9`N=bWFo7~p>{M+H1&5x1@2dKi zy@!VtHNo&s-v@@sP_In@*36FSg$cTXh;V8y%^3j)a!7RU75UVpprg8-wpFzx{l#>3ko7zJOjr zNt{DBca%%0rImpTVAa%0H0pBWdYxrt^uM;7$mSeY__v6H58B4MV?z_5T6v8No!f0z zTO=GF^1D(%=^;>Oq4n=~)fgPO5pDl~#m*{Ndb`$nL@TG&($PsXLT8>5x6@&Y{uUlxr0XIqOVsz~TkIzY{8^f_^F{1_C3 z=}%FtQ6cGu0rbJCbqh6!uY=*zQhqiM?tCLJ!Q7arD>O9}eht0687Ja?an6&~ zXC`lvU%=2K^J1Z$20ZTE)CdQ)#3g2En# zTTaXE%Fc7qN*-S4Rr}VLl_=!_Oe|MRwQ^jTryA!D|0efgn?-)h5rX0UQUQOO4pMm za|-qNxLB1A?1ye?g_iq)tzG@3W$XkHe z)P&S&rmETht7}b8fii_KiV*+tgG-*(*Xo8&$U37iIsITE(~IyXpZh?U4!0`4iR6S@ zr&}4RNbJd!MyE=v=AI34?CXe&b?b`4H}v#xZZ@AJ0GW>*NTHZYaL_|u-Yslr9l^{g z_Oztfo>c8~esD3k=GPxm;Y3=ei`17uv&>ggF^xfO<(Z$7$Lza&v1_kU7llAOJ0ia+wp3qvMYil?ngg5 z^VMLuhC}~}I4JY7ow1+w*AJCFCqBIe(i2iOAT4QX@^Lm6C*{Kqmr!6*?FMgx52viZ z4JP_4T^-mbF{`9-4#oq`YWTJ}Glju*A7Zn!Ph*P1Pxnvm4aSm!_okS$A)klXvDueZ zk^z3)o$D!Q&y+x}r+D)hG|o%K1jMZYX!YNuIZ&>a4k`gHVfFrv%!y}I3;1A7x5ReH z_b!ui7UK5oZagS#brk~X7@tbn-HlzvdcCg&!hB}#KJhK@4rbbFvT(LZQFeI=_O0cYx8kg{xnpn`gM_e$i zEIZrk3}tjLyD2Gj%`6+Bf9224NO-U4U0mSmWf}tDQkGQNiV<@)1;?W2e%yz*5yhI5 zso}HvI5=0pv9M~|f%Yghsdkid^Q|jvMHK)ky-Jq7^DNw^#WIU5!m1!Yd=M5C&gS#P zaMCsw@|iPPfSLy~UM)-4+e`bS_Xxl`q5xQk#=_<3==&*f6=y*&loI(|7--EiT&K4q zY}Znoypr9dqnQWGT&T|!Nn&Q^W@WUT3y_;)+x)YJRJwjE6+95#e1f|lP+`FTRJjdpK*|9G`r9OHg=CijJ zH@?=l0;3>wrUeR~0X|uSqd%%cB2&}`xc#^Nr3C4|0FXl~uj>Gvee-#D5Kcwrg5B)M zj9=hEt%mQHdy}MU1)2B4Y+?o%fW$xdvM_CXv1i0RAzo)lPPxgWn2np3os(6v)*1?c zuZg4%`1tsTCSv^-jjUlmghra9Gj{vd`wQ|I(&yT@&{;>DU9v&I862X_tjj^phY6@$ zp3g568~!kpnw3Pof@a$o3=tXe^{l936~hFy%5dI~$-G$F?#N*81xaHr_rlU!#@$28 z3@KAKx@OX>+n20hk=fig$E%y>FvXBCxx8rd5c=*G`){Q+xidYS^Qx6Ve|eS`hz}7T z`NzUTf7DG|OI-MHRfdCnf8S%QJ+o(oo~PQprY4Hl&qT5+{Z+{D>f;_P7R&tH(IBzc z{C?3=&D_cAVp{C#cY|q;t;6* zX(_-3!J67?5(f|y8SSmxv?N6OeozEJpLU)o?}Sofu|PP!Ri;lP>G_!wYjSy~_`^*A z0OwW1fyQU$AsDc3Q$@JR8_T)=O}48?>fSx_o_j=(3rvPaUP9a|p;LAzmn-gK%j}1e*@4 zhAVQf8-To~#gYQ{w6v6sDn5Nm5Bx(baJG^Mdc$g>ZrEZ|2kjh)iY^hfva~*!Z&SJS za}5GE9=yELpw+hCj{1CP=u!Qm!6_2irP=grY1(%2qCI~EbG)?)U@FNWgdi~Y`eB(p zeqw35;8Kf2dfUB_a39{razN-9^=QT+`a|VMJa)3${Iz=4&fA;*@`xX7AyU?gQ80Y4-Z}>!J3x6M{Y#O z2H7ZN5V4(X&6>?yWKEg`LyE@y=^BAbYw zAt{jR4{5h<0~Q~hx6!Onvz^Hjrr4?Fhyi4cn|aNH5dZTSEK$H8C6?$HG$v9Q0s$Uw z(4Uv!J{h(g*hgAP)fd_#SIpUfNlCVNB804Y1@w!6q}G;oS0B(H#J-+L{1wuzpr9b^ z5C(AhPa-sJKI9$E-si#e(Q0s3(%-%FlSm7D8F0+}z(ZKMqH%|uberFCF)TD351*T6 zQQM8|^?|lY`*%b?JE)7B)BgauA3|S`?VW-jVdz69Mr&^AwpP#P zqqEJ&qnK@UY>64}A9o6K`;JHN_CTrp@IzU6#ogbd1Oe9eu~;qxMLLba% zmIMcOwkt#(%H6s1PHYA9Tjc;O@&B=a{j+^;bk&@u4Nvo(=FJ4bl~vMwN@jlhHKs8! z_&}w3xgzo6MrBU4Np&gc4B+Gg+|9o$@ls_>%UI@)*a>ImqC!?ylMqf$gU@7lZ*-vK zTV&SE6qXDd!R@qn+qc+&SPekP?i)nM#U%hz1m8tGG=P#82hDAIZ0$c3qN$LDrY~bB zLfn`a0ToDzHnnEO+2kaWnK0hKHuyBTK2?N7Dgb+|t-4)Q?Z~6ZEvrI|~C9bElxBC$}aV@_?z58aq z4lJwA39cri?SYshb2gD+rh{3x0X4?L{VH!0d3j>uGB;PR>roA9W&hm)0zkgQlx?8H zeYo5h`_O5-q3P(Qn_x(MY^I>=drwpI7JvE+2LtPcl8XHNiy%H(SeAHKg6IB%WArT^ zAVm9e*-$%p@T)U0%qH-B=;3rVP?H0!_G^;P&aCzOcORFtXH7KRlQ_|$?z~ky_L{o7 zFWYc^QVG-RXXK65I@ZSFUaR?^Y`9?3w%KLVtvHG>IBK zGhYyy#8y%Wl9qAsaCt;PUOxtK8Qy7Y#V2m<3GoBgZ`5o?>?RpB`y9x(1EQX;G}y%# z>r(?_GRYQyy;Z>ji%EaL5i9-mpAuzH#I8qvuhmGkj=FYObhz$;uoM$-;4Jy`=md_K z-pLnal#>1}L6@0-lVd;bso!2n>6C=k_;hNv_fEZ_ywfFjd!}2f%aA+K(ZM_&TnvH$<#-T(>?%lt6k=nV#l96HW(5)C@ObX4yhA` zhs=dq-y;Ago1fQbXJLCGidaRj4g*SyP#c73K^Y=FwU+;hRpuKWHDbYdSvJ<9^!D?v zUWBP8C^^3_dT`p`tssi%dJX>F4SrBwAd_;=!p0#E-uPKWkLz%d2N6qxMz@_;`G$ZD4wyJn4m4v=FCi}tk9UvZ z$rYCWnHZ~W5iJvSctnH)xiH?~wwN$bq>v@#O?+Q1bRa4YR7dlwdqY`{BbIsKMwv@A zix&>Qr$61oCa!@c-J6D+thIDlofhu&9Rtuu{h^rTTxr22lER08z=0`-jf-v1bUa{q z+TT3*%t|mMp{AzZ8I*RBQ3mADTxm2}-4NG#ECU{bzB=qgvAUqrpf zfDh+Bv+ggI9L3&ic6Fzu zOqLD-Z>A|CEe#l&;C_c=41ko;`P{DQDJfZmaP^o0&2nOnjQMtNCqg`*Jb3~}Ad-xl z4d7h78uI&sWnT-Oj-0JlfubfGUF6>t`bzKt-igGczx{suYXK8%(u92yp=Ac4z=Fz^!9=f~Ex7FYKj&Iy??-Mzv{9>fIVwlW7Z=w{=f_RP z_d7E*&We-HYV8&mmzPr_3!=a!<>s#bMdbZWc$qMi|2GIwQMmK^>nB*3mMM_vOO~|` zm1ZT!CQ?&gk644u=U*HuPivLr&(}H5RXX!*k34k@vKud8BLkFlT%; zwE6`^_wqE5juso{Y{G>>=ITdYi3R zb&Lk7PXjviDrZ@d@I^yvvEFR_!$KZ=mb3#zZLQz{-o4lmPFqy07q5w)y=)V-4Zxz3 zvHf_6RTPdzLHqKsO>tpOU}2FPSAF@aXY_;rzDVNheonA<-JR3I6i9h;&`xk?H0F1?fyq-4B@9bCSul#VL4P!>!SIFIEl=*7ja*`7!)&>~$E4MuI#ubWCWAmN_w1BKd_4lFS!I^Ts8x>Sp8vMnIit#t8 zcLjxozq)T>0KHp#7(nm30qB!F1*#ZXtIH~K=0dY~MISWwtvy{)o;q?VP zL$Q!;@$@27A^)ovcr^U2pt#YvLgb~D?$N5Ngtqp3CMM6WZ#y1d_^`>47pOY*UhZ+$ z+?9+9({xF)r0Cj|u;WqaR62JO?w=ucx6@yE#K+}ENgE%9^bhqf)SJcJhu6i61uESh zJH8DRYQKP?frIVWLWUloc~=;Z-*AQO4J%4-e1&iyd2%ilHHktD`OEl0<$anSwu zDEp)6i*ymn!4Yj9Zw<-m3=~n+gPSXUa2OHl+3)Yz|K64dzk2WeccuM#wYw`A`=gDO z0fWh|DMHH9IOdJYTio3c{3#d}c0p+&i!J0=sTRebkpkD|!}2XbH>?BUf|Z3a&-<~d zeXZ;V`&YRc59R-E0LSy=a>p6W0jHS%COAkEypr-6|2<6XH_Ddxp$DeTQBz*akSm|R zlTbghj1bg?4#+7g+dA%K=?sp895xyrSRVgU1`U!V={*WLV4|(O_?r`wixZDLZMppNEbad=fz8)v1(1Qb0 zC390DYG0XJdL~M0%6jNs1HaYu^rYRWjxHLQ?9xwJYcqQH<)k$D_&ZVO4BUfGzb@wBjrP`jrkN`6t2 zmmSpLJo9Vm2EMCdE>R29Nk{KwLKUvFaBSN_( zkG4v-ubrQS{~J~ao`&W9^3?FSoG$dVxJMv8Pd04WxchtH$9JUYW;4H+N*@FjCn}Ze zlhFjV23(pl)))b~O}qBYwPgf9+;`h3+Y=9i*_;61t9VglMlG zL*3u=fUX9&uPMBLx=4s{dD`+QM-t&D()nGalf&7T-Z~q0s(nn=8ZN@j%htLbePyNi z-gjv@#gLKRxhp`31kNWz0FF;vdb3UU<&iH>p4}&dfQykns=T}+Ybyi21qs;cLC=$~ zqkZMYnsm9(y_?O1JRy^Hr4Is61W1t2s{)XBrJt!n6oeO%042)J!}U0TUjK)M1#WO& z9VzhTU@SpZ-f?RjA18#vfv>c4<0m6nAOwDjcz%M-)Aoa+p$#ZTy3OpCcEBrXDHB0;4|smQ=)Q-Az51}7C0iT9_{ zii`>zfYJUm;T1F?og zE^0;@3XBM`tly&)Oa@OWW5$1&N5`Dmodp9#lasTxMMOVq$;K!ljb-XoL#F)FaR86%X=aPpDb7$1sJO+7z#5SrR}0^z+>=UYf$ zUy7Y_I@MM*0UL~YXg>(z^VpWV%T62Ttxq4{mx}VR(bYQ8{PAFZug!mAHNr|W+P9E+ z((+5%^;FN`PltBRTXGs`J@_f36!I}%d(=bUJF=A6V?SpN7AJ{Ns!uNKt-Do~B8hk{ zXj+2U)4wp&DV8RdJC~`kAxv<=m|g@K$9nr{8g?~ud=_N z3P%GuVSfT@-s1BDq#t3HW}XeIBrysUhQLZ$0(xL{eEadI@nx7KiFlS{vLd7c1@Dvl z;YNf%Q+LG2=<+wY!|}C-ixu^qw8|`w>O)9kA3@_Gzsjn~lC(IGi;C;^qu&35p)`q5 zz*mJfehKeCiuwS5YV(D5FBlc zFw+Ex6)7;*$ie9nDNuiVODCtSI6cXBUT+Hyniy$hFjNLe1_0C%#RE8tM%sschb4*o$x^fV(TsnW z@zHWQG5ZRBc_FyqW|36sS{WF-s8wHM<+RU*$V6<3~ zv*+>>2#-?j{WUQp^$O0Xu)U_1Axv7Tm@Z*B($QTM~)ZMNHeoQ z06y&y&aD8iiv$fDJ!9sXV$mU8hQtCn<&vP55-i~D?p}P=IQbOkj}Y0N(WzLG%zncP zTCf|fvEiEm3Um%<)5Tm-=xuaiPXC8*xZ7q)Z+E7(q*f)7cXjfW5~CA$Amzw_Tz>Sb z@7-(obXfRl#rSo6URNP&V!S#;O7~)5ke?PsCpS#{jEAYWOD{aw7o17pv#}l+FpHob zGC-;;#YhtwOc)~4de4ZNO*{H;I!*MCm%WeauT~9=WpNm?Y7IopPZMbfPDx17#U=DT z+|12WV$L}{EyII5SdN&q8?Kt1@8-%{w0H0Oe$PNW)(iZ3L*8MaUt2#`RG&IiiXRl6^*QEOWp5dl*@hn=4QVvt)OwxfRx6 zc$u|o4T4k2JSOrf7oz`cW_|U{1FUz36f5|XErbXsCNV|x_}mcy#IhCA$V;`f8_pef zNHBty;Qg?%CLc0dX8fXCxKn=2uXog9H!o@ATa5wLuID~Zmny)Qovq9Qa~|91 z?0hs;|4fRUWRC}LoEQnnM%VnWEQpk_{}Vp5cO#JA&)YsaB<0t$NqqV=KHJxZC;?#n zLxh+R8Kru>@A!F0VQx+xjp}AP-}o46^Xy6|l zf#fI0X_cRE>(ab*%8bHtTfXYKn1(}JtkmBj(iL}J$7?64prz^Zy6^LN6rHYgh{$rC zL02OqNdR`|)2q0)Kq<1|5g2=v(aC-va)G&)gAjOm+KG6*02}WD$Cs0p$n#eN6CK~~ z;rJ+HZbA6oU|Ga9Jh|xSeG?w=;?z60ASb<~1QbkJ8tSVk%O}J|!2^T>PvhiMPl z{!PrMs*O9?6TwXI;*q5ONYm>* z*N-|d*gzuQCwu9~o0g;8i!-K*Gumahdv#-dWe<3(CsxuIWqA#8xI|O1Qb*NdfAo7n zl0g4+^MYzzI3NC8d*vClv6qf2WbZlY)=TKnT8$erVkvi*8pCw@-*miR-%JBfhCY(y zy&+?`R`rq@tIesZx;}2P0{F5O$VcL9r_au_&>k?1jO~@MXmu@2mQer*gr$;k0%MbO z8|N+UgX6%xk;M;bf>J3_S>E?F*|y3wRK<6q9V0K`1vr{x{aJ-b(0t`38%RhZehhyG z_(U`ilQQ+qtm2|y&u2Qrj#qrXtGxUh>!y=UN3O$;P!pt#D-%w{FB&$N7OJWt6O8u# zRFs+xB-`#pt;BR#!Ju@7$Gfi-v|W@jQ;Du~MgEjp)#{2OpjD{_1#@8uSzIn&GBsDT zybnuFrl;mleZ(j}KXQL3k7yl#BO8O+w3wv&V0&pU@8xBuaDOOW*eX;1cY*J&Mml{ch}eA1`6rZ$G^!L4t;?Xi~8u_K9c5? zu3+X5f76NG)>7PI;x4Sa(dvD-E6Yo#q&N-u@H`;c%sUIU1PhV4rZ!a>UTle|@_hQ( z)<3n>-9iJ@A%C%PNJdyKC>YYIvNMDoMu}d|m+5=S%ePH`#Qr-l#2=0yVcxzTK|BJw zx)KWa!_tK&L%KEgF!^+`w^$pkUR@qHOKc;aVD42=|JXXclc{<2=(T?@?WMeVF#uge zcr0_;TS~!IMZY1uT~Moaq>B;pZJmaBgC!0*v6njoSDz@8&mkMl^HY7kQGJH?l6!RC z`qz=*o(0}=uZjZkTy}i&{5t$P!^C050kSRwS>u@jT)T*w;ovQZ{&Ts@zs{?oXQMW085yhj$NCnb~KJqw0yOm$sR&(Y0{tZ+{RR!0+Sm?Gcrn@g6Uya~241E4g z_fB?%S^eO(0J6zGD>pRIq_`31s#ye?#qj#A=A9F0-<|-JF&yUYO3>62$t@|f9k+iA z=16G$v8?9?_JSDFS#&VhZ^*a?mObSt^m6IA4*a*Oh?8MquLYzB?*_|RlALv$&M*K& z1$A)ZZ5mmt9kTzu6s(bq04DiN*^on$vdDU_>_xg8$%HyOT+4a7Kjs#c7L+PvTYUX@ zFE8`Sy*FB^&+w$>T>Ojl+f4gvq0PEEu74hJ+g_Uck!~ovtWFyD4Y86pMr=VIbM5~; z{Q7o_`Q*BlaP` zFwCG)Z=UTgK@JoOdV$2zdmSb>T74AxMgTRj@6 zXcCsjs3@(?O-88?3%xkC-r;qbS?B`GD{;ZzfQPdUWE>=~fOx5?aTZOtMr6{6KCjZ$ zqvh)KrXnc<^Wlt`0}iLzCO3IKFMKNYDI7dN$Dd5T7sItC6`v+cAwPo%Bp+I>m)1do zMU3>k-u2?jbN%-1uw!3V&XHzoPNGiq#tOSjFw6D+g?(zK`hg&mVaY5m(3wd_6 zRT8*r=4WbYD5=>W?^^C^ODS#gNkHs@fWZqfxa-pU&ThI}xvR?`tZpp)$h4)QF>j+@ z89&pse|G@&hmZ==az6CL<|a6<@m98T}cZ)*#?1rbU{paWmNkIkZs^ z^JxU^lv<4b3eGKL7e`3=+dTT$GvY|bKZgeT9(SPr?kH(^Of&F6k=1 zdx%VFLDAcdHMx=g(%Ch6W%UzZ3lps1=DXT;MdLwE?^9F|R8UOgTA*Rc) z?HgCRc)PbYOHQ|x&-5atjooE`AwRQqF^#o*u4L%(y~%`P6iNFx%xWe1|s4n==@Hw=I1= z5Z*c4TBO$Ew6|#T^)58oY`OdljPcnBn$s2XozoCr+cGm(0X}_(#Y>dHbrqf3gxQ)f@Z%~CH~+5#N+LUVeiSTLJT5p`}BapUG|oJrRl?CcIV zHkynMA~~MJB)%2qTf|~uPr9;y&1^rI&4q!7b{_W+oSxZ*63j61FLk-RNq*h$#as9>3Kc7OA3$E(A^*y`+_lf>RruKp9FsvP?Er1 z*CRJQOcG(*ogAi^-z-CjyRr6V=uRr`ko#z{g|)~g4)ZM6`vo#dD7=rJwG0@a-`5*n zkl}>zIQm;kxQ(eLeR%#%B5A zozR4{xMt6r^ZSsVE8S-{GqygN?aB&y87t=IyG^GRj`No{EnzJ#ccs>}p3%=3=$R>L zKCZ>Yh2XJu)z@m;DF{%#SJcN2C}bS<+~}CrbACjOXSCN@cl&&n*p*<+l)-@63 zfswJSFD-EII_petjP*UF-XQ$V7R)vNAefU@ZRfViF)^B#E<7HX4R@n~D&1rfjO5)t zVEvo~DTYM$`1A;YrrNAWEHNzy2`z_!Yal6lpJ!)XhkI>cmwr0misx4R-7y2Ova!I# zMLG&wqym0~1xiW$P$bA5?uVFzJ2`;620~5_E<^1`$D?vVf=)73Wo=S)joGSHddJxB zu{Ay;s*2M^3CsQ6UZ;>*lTdsF0JFrLJQu_r4ZHo)-vnGujzTn=%-=^8d-e?5bSMUT zgM*+zphbZZ9gCsMc6M&I_9?*PI8-!PHNqGj6Fa4z z@%=lNZy%TAY`_d@6or1^3joxw5A^fk>p=Z(IH=B!K;rF)*X?k!vIpE_Z$37iD&T}X z?#{03;M2hQ41Wg6slGGK`RWUH54-vAm@jSRfnVwQAENqblX*z60ztH(FSGUFj7xaq zXK-lpy)*9sISK`0YD8?sZd`&;Dmm&Q2u+yu3~LiEw;}_Lti}4}JhbhU=!kGWsyZUM z6Ts))nKs~8elZmWVxZ{WCjVN-`@^NWh34G7;8p_Gs^>UaO-+L{kfyr2GFfs9;4Qr& z`7$hgK!e-ecdY4ikYxdtvnM`8G=K2tu6 zzkGoPN+?JiI2tgjdw8(`Kf2ZeoJ&S@PpJ~5RG2SQSuN5LRjsC?(a-}st-uN$12UG3 zPB5?IX?5%W@%RL;)!5BeK0Pt9!6Qnl!~k6}N=fA9`!^Gw-pS1_m)D@t+z8ys?=#*? zi~UhqR`Js1D(HHDVcrVVYwoEG20y-*$impzl*m@Nal0dmdihLXEtBsz%nqODLmN1E ziSIQ*lkU+wF!V?*CgVh=Dy{8bsL@9C9FUaUJ8vZvS;_lCMdiZs?FH`GQ{>3hL}tSo z)0>?7800bY4>ZNfBIc2S^~%O>I6#@2CBF8lDzDTkfBr{pGDZE5CsJMjpymEGy`EY!44aNFv_8+VabB@JP1CnuTWD_t%QEU@ADBqgD@zN*>{ zmqZa_Q#Hkl0b#C>8~pFx_yXw~*;W>*kfjgM49F+m{hT`B48>#H9KINk(2)3Yz`M~N z(zAs%bs7!!eg@BgZ~qm;kd#^RrK`cmxilyk35-A@j$gxMw3Cai<^iAi-|0ZO#yXlW z-D0z?S?A2hQ0)c~6P$h&^y2kYSC%eL)&83doX4y_{PAR9=K*JH4Q`9aij=!BMB(-_ zBG?7h*1%PZ>*1d5HDokm9awohumIhedkRm3+CvRXm4s67O!y3Oc! z_PK-cJ^J>*=W{>XyoTy2DG>zLsy7*4HOfx z>9$zkHDkA-mtXe@rmeRgDgJS8rK#Mk3{1RsTZsh)8Uh}JIllVsCk=^2;DM#u>DdSNr)DG{`))r^XJI;;#v0>Jcs~_ zt7Y@9Cyx0Zh~G8nx1CpOa;uaq%Pajk04U{Uc?3A8qvKO7m1QdO4-Tb|har;S%7fZ) zfrw<~d3381F#D54wx((VA>>o}C z{zHrRAMg9$Q-6MdZJAzG*^OM%-;`@kd^f@=xC&cZbJ@++xWbX%<|4Ic>sUFPR+%j# z*iJoYD~Fhw+D;AJHJZ48vAV!joc0!VmBj6IXt0NYar+{*Iavdj287L&CPDn}>g2C2 z1%t1`8CIX2Hr38~)Wgq~J*+VOrSv8? zHG?$f=sbLVp?f4iLk(O@)i!P zQo34;fM&P>2d@ztK~$^dY8)WAE>5bjBAc5+`yge+griE*!B?z%+yG&++0meEcsQWa zKjWcp><%87bgJIjePD`!D#MoXF2m%lEUssqGP4v+x%&DnYmf%ynn`HstgqhdXHB2o zFj59QE|{@_>-g=%d$!F5WK>-Tf1wYWbdDA*4R2xwsNK>q>Mv{P(?pHsp6Bk9etSOB zFlz1~imy7qGOGjM!XPDhF*X0)%&8ji*`H5m&^+uDLI?7ygDMGJYBHihp01(cE^J8_fjgcla^v8kCk%p4VUKE80(kngE z^1gD2wfE;_b6ns1-17UM3a+d<>27;8yrxdI;itm&VHs;q+|f#iygAcT3iUMvnLo)n z{D)fO*U#X9SKm3+Xzh$}El&0AGHb7+{S5)1%8@4_GC4rF!+Ca=gz06aWOtX(jMWup ziggIB@nzC?yMy!2&HHb0C;8;dlx91>qVX{hkb$2foH!v)&wR?VRVz!LeXLJb!q>>3 z+kHO5rOG5vkjs&KuAZB6>JaSOEakO7%&hbVOF7FOo|M2#NG+zLD+axGfPdKpJ8FUUwi*+qDQ138@hlJws^K(X)OdBU(EfAdZfeaW-2SGx^d^X zs9C6&NlvTY>?-7)ds+e8+Nb=J|9R>rT0Fw;Cmg(TSoOlGAcl4P)ufv>ogfjlYNR|!!3 zhLwyA8791)co?&amWs4x%`&e{v#$SkST-2+6?Mv9EHdX{xf z@fMpVrgHh*w~sUzRk9S_*L%nsD^!&HjKp35TPsp2xIyPWp`;Ja$0e)>&B7Ya$4&J8 zL8{6p=MG8V2@K`U5M2);Kn1Lan(j!aT8FJ8#$3W?%Fm8T<}kjXUIVN5g<^ z9|V927Z@i${SA6nQ2j{Cds#7JpL@uynX|;Ab;7Z8b!h}DHe7dh-)UXCK5{V6X3JJ; z@dn6h?JrGKPiYU0HG^#a;hM5@8hpzOnYxQko4I6Rklqo$ZOeoPgyPBK6_%8|dz&Pf zE|*v%fsBcd=5*5@h)7UsRQNYK5Hc;fgAqmKq`9YgGC@w`c(9PPKB+XM+c#lu7E63o zs47fH)Fs2<340D4=uGACI_BhmfuJ z&hugFZHUv)<-H_N@(|m{@ z*)ifuw}*5$s!t34z*v8o(iQU!m8xVwD6(Lqou^cF7dFcCuyEHt9r&~Jn^U7mKPh9Y zyyzyHDNd0Sfx(ZFHM_@vO%P%?$nF^3*x>q+Cq>!Y@J^qhG1uIp;}lgrNF&jm?weTA zFvU>)8=W+yK(oBzk&h455%IEmtcwZ#H|OqH(os(V3>3k3Y!jE8Ts+r&u4WbLH^^2d z12fvFmDYYwe2m%bGXrI8ISJu>zDL#HP-By5ihnWhFQ2~1_m1NHvaw$uC5kotRy0Sh zTPB&qU@6jZU@I|Evt+Ts8O(ZDiNBif;z+965HLGHl#eE86goIu({3uW3rCxzhG!TCB~97JJ<61hm|$Oi@&%pXFZKHBJZ3w@`OusKD% zcMm*a052MCq(Am8JuK1c9u)vESX0uwJ}CB$o6A>Xk&@rtrQ0xsp#rb8OUhOzLgFfV zsc%e-sT}3aFi$XQ%kt0xwPI%A7iD(dzF>|uZ{zjTmO1Mh*Dw-8{rp!xX1|6$h(t%cwhnhxq@(G(J;EHB1F zVq5DHM|R)=CDxSoEctpVhOiM|SB_#}%KBi|1c;I78ye;)a|er^UjXz8MO}q#PJ62o+445p zCmd%`;shxK0PGy4S>YB1%D|<_&OEDP#KWwy$1y&PDHyO$m8y8ORtHY8*KqR7A!I z+nubnh_S#8tWj8l5^BNf{;bJ;a;Y3Ccxb8BK=8|NPGNsqjdJ3T42O>gh2A=K39qr6 zZNPR~g>0hV;ki9MQ2*e=$xRN>I_MI|^O=&T3#f-n=eIXeZlSPw5Ng$}R2G#@8-Wr& zSh30D0bi6S!Ai)f{6Z!`tI^?b!B!SFsEw=Bz^HzdnS+Ok1gxo<7dkW29EYIADorLN zNWrd!o(cva0pISuhZ~Ac0?2p^m4@2hiUAd2zDv7B==!Qti}ZJnhi*^z6Xq87=k)-- zCo9ls6*A24bd8tJ{22TMviz2L!yn;+h8o23eEn?Ai1^YhIX!;(2|j5Az9&Qv+@?0B z=_2bK2_xHRTzdk;4=*yu@Ht&%iYglof$#4*ws?Mohe^W2W3pJt^*B#>)gt0n`m^ z<3r~?)}S-DClsQT!VWaUBeUH%SxmCKcWiJ5=?gQ%d@;(Bm8X1DA#(Z(d`OgZR3Tx3 zAQ-paW#2QQ$lHued@7iiU%we2IFZU*4<5}lx_#{%5XQjBip$cgPK~ZUUwyDL!~LP2fHU2SB@HkUG9SynD43FRoZ!(d01+x`u3>&dP=gpG(KnEH&q^k!^mpQtA_>` ztn%PtLz)C8e2BL44Ai;Gx;OyM)}ZL*txWG*6fP`yqRBuH{xQTGWg@_q2u9b=Kc0 zZ(+{Pwjm%~{f&wvw;J)%yVkrTbmjL|8{APrA?2QwO`gU`eoOjT&4Vb`P$C}To7wup zvo_x5Zsdax7%woiKL?d8f!$uflApiZFIh7A9^M zVp<#wE&9LdnRFq@Ee-P^v2V?RF*_L;b1wv`elyBQ-!n!992~I%MVL|!sWE>r(IUKd z=X_)kFK(7kjMLpHNOFuVTr8=2rhAa{Ib+jZy`8w`< zj%sdPmhP)88MDP|OYsNf9uCTQeV!q7;6d=E0ltC0@lQIR$M!q+rK9rW-gK%&f+r9sGkD;TOrBJ$hv6@b2LYTy=0lG1U3hbQp3 zT-e?{&}Gs=Ikt^HplC0hF+xaQGBC4XB4|ywYwx1crqWZWTo;kIk$GLBY^-kh5_j<| zt*2lP2Pf1NX5A@ot6uFSOI72K0_3UfzJ28!u7q@!Mv=@cIq`XxdN0juOjk`yJw;t3 zM&lU3cBhx7w63`XfFLE};6 z@0`6tkqgfwK!=7SyPJ64a|RkJL|;VU{@xCdiyjW{W5L-pZFCAJ3dBk? zWW32witmX-`~aFF?7Q4f%S(BMj#5hy|L1*Z`aD1&>-n?;tdtt@oUdRUM>@4LmL~YL znwtOu+(zZ>bZI;sZlCaS|`I_n4pg zJO+E0$0He(Fkm*>0qpMg$9tn-pC9ndXLvx5{}CXHk$6~c0pZE_r5kbnlo3%e5ovKx z0shA$(Dy(lStKQcEohiQeoQd81Y~R8ne~0|&H+AuHjPe573c&Zp){VQ=HWFQy=5nT z92C+{;Y}zMCm~)`)KA{5s^#gzokLBmL^cRN-b{2e(_T-A@>F6MgG``)d7TZ6xU&iP z0IgD?dvv3SYAYLi6I;624OLxi*!7&;i;i>v)M~Ak6NfIeeaoioIlgR*EeANS8<4;e z^}@8hykyA9p;x78R1Lq)o82%$#!%7-KI~eZl$>gPshA2x<~~(9Q&H4?-kp8@H>h(n zFFElBr~g;JNg-1-a`}eR0rLFeTjFKQMgzaHA`PBLy0Cuv^2zlsh{ZSOwqUjDn&R_- z>e3%0sJb3td^3;3PLLwCe{ekSLNw(ii`w6eeWEvsd^XFC9Pmkr6zkc8i$==~E^lKM zDZTPUAJ^u&X1G@qeu~TX$G}(LGdUP8>SM&=Z3$Y4A|l@@xqcad_XLQ}B;;Jg5X6kW zDvs35@+{ct=@LaSmcr+zoIM4E{mC9qA`S8jkCs9$Y{KuMREu7hAr#DK=HW7gNtdl5 zZ#H5@tr`la#(JGLeH`e#YXZM>wZ=yI$3_XK+BnGZAp%u6i{%`-Rof4|OExgQn`)E* zu;ajX$`w1uGMmWcFaT`Om^ZIJ&zFm~{Xp+@=bN~bR;?t{kL{`EReV=mf8dP^C*_a4064nT zB^Vn#KL(o!GW3frD&2@e28v|p0@XY#nJMrAjO?Bx*Fn}P=A@m-y|eUf?TjFQRy2Bt z(71Ic`U(dSEH#&87S?($%X@aH%qG0+@m_|)F0=om zkZ#t)hz!w%sc){|j`jO984qf5S+v<9`kx+7PWU#mAw9ca*dI*6RT4hVws>1O$TptrHw zpCjuO0jb{iicFLtBKPQHMQ-PZY_?!{8zoE@@#@vjUPDH}bZn9esY7OO{8 z)M;ml>G;8d9GdE0Qw$I8E~SV#S;7{N+tpOh8U` z`urkTfuL#1zQE=)*nf5uWK(}|;jxNJYGMPRXROv~4w8UOvQbbyoO=hq^`|!dA1y%k zhpsIZR$b#L-T%uUGHBv_*<(Dig~Zu6ZSqjJiWJ?d5Hh~|=&>`IXi(D*Jqh{-W`-s% zlRW)yyldMg9~sM;y-IEFb(RwY6~3y;fALZ=J3hD9&6(E7i|;{AaO7_hmx=*ny+{eY zQAp+K(6?3|o^d+rmC3|3p$~hFwIdC9*RzHDR8fda4etGH>rUJXOBosyZ!Yi1_F-xV zk-s6&MOvSn)ba8SryM5+AEN~xd0np$^ai~R-S4$p-u*g@lOXqmv`l?$+0D$mBt*yT zOG6~m$BPZz8^&iBXw|EsXN&NkP%}@{Jn)3M7WZMF#ZCuUAv{Kz>_-EDBUFr?e4u2Z7Q86WK#lLZ*7OHY3K_ z`Zuj)zQq&?=hsO$@5@YJg zIlS|6Nz~9(g=Jl(g#W&>9YYI3r0E?2Mb)G{pxBI7wU}=Q&t2G`Rjk-wMO7K>9y~i! zd*XcureKcSkPE6Ns?aX|qfZWNxeUIMZ`OZx+b|3J-!S87duhNzdQh#eaL=CxN}-@4 zlNkF`e9El`Nr2O2@Py8E{-ff9xu)yA^o;ZGQ=mmoOp5Zny3OWA*}rG>F2+_XRxMSc zd^r6AQ1lLfZxe1)U|~wxy89PcPE@gPhM{`iIo!@MFwZ8`YF^KtihNEo9anm*!A(88 zrJ;rE8CsnxM6?ElSX78V#P}Qg!R+cUw$c;5N5)~TM%HHb>tndkC2Lajz_!ma@f@5a z)M}J5p?I+M^2+HzXE<~7y+?ZUwSaIRk{M4_yp)gXYdz5Llg!^CmjEfCm_WQ5JidgVpK$4+yJ17umA=2Bv@5xtnOp;sb-xZYdd`4<57HNrT$%tv^s+U)OR>@Ah2DjRXt~aykcCQFV?lVve8zBaNQxE(q zE-Wq1l+6nEYlpU=dZo7h6e1~C+ZXI<1`i57Cu$Iz@gaoQx#rnF90xo2p|yC^A?9r- zQ f+b-s>EX;NQpK7Z;g62gYKLko~o7cin$W_|`oS=xB+Uye_Fj)u;c2=WirD*x< z5ixNHa6r0mZ-)Z_&XGgDgF|(E81j7z?{6wMmgxN8eNHprjb6NAeN#()u&;@U+l-PL zWoj-Z|E`sUn9cO|lf0QHxxuvVd$>f5Eb{@`@35X+OV$R70ArAFR)mkmq z6jYEf@Z^Xdd3odAJDeqSZ6&H}SnTaizVq1bJ?YFmV&+)vIE$8|^t{_4JqK>PQp-XAYQzy%NNNshhqVT2VjpI_}q)x4;x}^-i*J0o?>TAV4 z%xtzF8TN@O3FQVIr^N)R8XOHqM%mjicyDVeC{*b` zLMD^0iWVz!lU2PoR%AB!;EDc(I4m^(PrB_CtW1-i%yXm@$g5A`_Iv{548<$&Ep>aA z{zqReM|VHyg`NGYB>V$?9TEOf2mE87{(t|l%*Op_Vp@3aQkOTelO_fsDPK(p?F63}Glq}L*FV#kBzvj6<0U;oj%b6tOY>aF1L!#i+!$7}gDM|^^2vGSO zwD*s$f^8^!j;?52a6s^(J;+C#+>J+FztQdUerSLrR{yA~Rjqq;Y;bm7QNxO>)?m%^ zwTfM1^A**Oa>&k^o6+^DMMB(@Jy)@%^}P54RKO=qRmWt@YZVt!=L2YuZkClQI>y8k zWsFBS4vIJ}o_=fyuX0zPFLqWfAHxKh7u{po`-6`FMML-t4r?cTF7ne#$#yKAt*$M~ zkI_a2vrcy}h7PwB(wUdpILtfnZ9fqL2-$~Oqr9F*`d3^s9Op{ncxSV;#!T*v=XEjp z{vb*UBXakLu8kuP6U)IjT}QXTQ#($A1hEXcCuFISL7gD~GPnPhpygN>*`gI* zirZQc6;1gCWfbCWR8&SgQKczzDa1s+7evavakE&1Xi01QRiI}RRFS8kTUI(UG;cKj z>?or?6+`p^J2E!d2+E{*Mj#qM(?p8-BL+hvBQk|{Fw4Rg9hEyXzhV%2{w$x`V@DY= zKqg(W(zBf^3Mnx8!{bMZwJMzH{EIC;*RV_l*$?kRw`X=XqT`ycl(R9$AhX||=-hSz zBuP>vRvAnGEoEY(M5B9I<1ssrcKbsQic3iZL|48+;~}sbMh++WaNdbYIz(8}MBHD$ z`KwideLwJvF`MFIp)rr87LHHuccm_`P{)|x+Zs5&$BCH&$eKzfUZ8tZP}xv*RfBrV zex+`0T65Pu&rMk7D^aHxC2Qah$#ioC04t|lzodfL$V>`O~99MPX5ziq)&9-5YH(NrGTP= zQ!BS_bqN3CS>3U)YL*8Y@K)B2G3lV4QK|IDK=AxS-nJEb#H_v!9k`vCkSG0wF?V#} z0t3?Wo#}U1E5m2@%Djs@9?OB_qP>#cpB!G#Z^q-=_(|}iD}393!TF4tie`?50X_tA>K7XSrg|c8VI3rKV~F7RrN3wXuC0<5%q`@5CRtr-;%=Bt@KrTQ z7P;r20w4!Q|9ZUCVgCpXQlc%2VfewDRjjHhLy20DWZl`d z)DiHyPwioL%*p$S>Zk;5)$3mP@V;9nN3QqdM{%UwFpKR~ur3fXKE+*TVPFqA*sBAT zs;i58e+rNfksc6H(&}8+PyOR$_fpTYh5i+Hk%jF~k3J2N8j^8aez&o9Y$IV)b##&J zwWC{e-r2>O8}@klcyWe+Uk%pBTQss_FwR1!VhjSfa8#MWb$OmPMLhyLtCYx`TA&42 zB+!5p+@7UO2J__9psdv7?YubH1+j|mL$`RRTN=Pn8ITm(5w9#8AHal@adKj}whT<;Vh^vJOn6YtSOWTZeTH9f!y|6OoCNoofX`2XN&@)(7c>iH8NB?^=TXo}kw4G=H0M;pbzHTl^~L_7m}_Luzh;J3v@BfV&M z|FCFr5o}S2hJQ*Rl9S?Y!(P?g6xqC7v`g5MzQr3dYz!Kx(Cknp(h>=}8g&*QgM3AT zsE+E%r(M{Qvp)%5Nn`3*9{Ow#J$+MK%S$iQSFczOf%iF`!CUW>0nPiS{454Xj6u5K z#OJ3z8UZQ~?^#iP&d(i8X?_2i7-Wn*4gX4gHpzpvX$(~*2KkCXpHA2lMga|rxm8V)VA3^=>yqzZ?oIX81up1 z3vhTI07Uv-7eRg=j8qFABB&&-Cw{|g5^W$uYeXWhY^RqtO?BaIns&H}3VisQ|7}eI zpzuh^+xlEIx%fovGgrDKXpuLT)1Ct1=^bBB619hdm&nGL)egA2Uo&)V-lGnb_7z6E zaaTp|FU8T-W56fX3-Si%QCd(GX%Uc; z?(Qz>F6nNN#y}cGx|QzkmJSK&M!Iw8n)mqqJ@G!}=l&tXaA)p`efC~!?Y$*3iB~VK zN7=X`p=BltZ^tk3e*ICAe$UqDQSqK>w7;tz9SH+eayS<<^qu`0Y7n8X!b7PJEU_44UbwA_(p-OZDp4x8hg7ke&A!eyUd(%? zww!}w>Trk`S_J_Tf@djOC*BjD9TG7*o>s z5U3+;Sn92{#MCV{A3`J5T(?b5zIKU8pB&ecbbxcU!KycFL-_mzh719bRI(eR^((1s zaX5(6g%BGa%F^OG?_>P(b(02C4YW=ddMqet;EF)+*C=Dt@X3{7WtBnlen;q?%KP8k z;k@+*gE2}-kYQ-gArO^;1W=zE;F3?VVkOFLc-ugT=D88g=0b^M|y}xGCg2l%@W+~F;hc^oo;*(PhBf8c z=&QOdMsIyMp8I9i(AxtytJK}RcS#i`i}4LtA5Y9Nh%9R>Xvm>KWtY0gWpM4!J@D%|C}Dp&;4 zvDlE53z|}1UR6jQg(Fq^gbWh&ztgDdnKf_;(NETHwN*N-LB_?hM#_CIw7;j5`d_i` zzEM@W7_FWLOFrX~NxS0kGVGm`U^1Ms1iN3<$Bhg%w6NDDq%7|wcu)cwAskh2$Lo6p zH_(@IA&#i~NZP#3fckw)@7o72UV3x7cekaxRs+mauPZ3`VCzUIp@opYTy6{T3M!N{ z)_~++mRG^Yx0}C;^~(Ibm}#NK4G7+XcCcn@hN0nVf8h;hF&|2CPOIc2-Sil8 zPV>9JO{bZdaW38~LGlmEt4nrgN|m7N9iFT8!7RKaQ?i6!Qd2lh4&@hyB0@FK&2a2R zA^%7@x4KnsX)Q`lUf8KpW`76^^kd_^Hpzvgh1~y9b~#>vmpOeN-lH za&j^egQj?^S9n0-;1rL;QC(1;g_6;S1ua<9JkaoVv{}StJi&WB?7)3hQ^WCQtoZt- zX6KOVN&Qu?Nl}$}fWf(q79cFGPiqbZgf_@EV&YSIeNLSfoZx*)lp;?by&e3;=(W{9huM6c648s@C2YD~PN@dlYb8v3%ei%+;l1CtCpz%4`qZH3} z6hmD0k;!N-7MEA+5|@mpQOS+I?1jEJdLls&_%EEAOa==G)Xaw${Ejr=>5f<7S0aD@ ze4t!mZvTKp_`A^Y^d$S6Z=&R?wfb-ogC{j*m^; z9bl>lfRejRm0VPBXkSyjIbj*OXlTYPvs2*^{gRJRO%o->#>QR#RwrJHA}jm#ObUyw zr5z$Uxj*Pn03*%M*`_jc0ouI1hxe*Lp7XVSYGj0hSDN z)X(I9^Gwa6wFpoR3u-&9k(@~vjXI9#e-BrJIi>5z}+ zA6Ov`#3R4m(Y7R3?M6bJf9DO2D9uAq>Uy|vg(P5{~XHnsmAtmryBtv`>Q<5^NzFG`-&_ruZYaj@E% za)Hi!)6WeE4p1G5*Y%ya_puar54SVEfOU-c0VjS1d9G#qYa62@F^|y?}bfu3xUTnkWW0f~5kzTcY2Mfwd zYOE~GOVvv8QCyslhjqinfg+`}xI{Oz_AaaXZU}P#`d*QN!J9|Nx!@HmX_hcg?r#2w zw{V+vqKJWK$084E%gCm4Q7@UR^icEh*|!soUX8;We7xUf^(8rwil_JwXKdnia-0ec zF2_VKt;)=@(?f~Z$r=_DQ&S-!vL*Vh0li%l;@K54JzFEkr{h_lylO#N$H6Y1kjz-C z0@{ds08qbpk$7@+WT>KoF=s{O`fIvvyPrGJ$f-mT5oAUc(heXPX00S3HFCVAiSbC9 zojg|{jAt~Q$jQi9F&{GEH?zSeefopV_ge>AT>RH*RxXExzTnkaT@r6_XDyg;vhzg*azB)jryA@fwvhaG~@H<9>LljoHeJ2Z22 zillW-Sg0>vbFO?)%o`Xi+_x<*nvEI!YGfs3%i}cuf+exZZJS72V=56n;@T^`RF4N8 znxInQszaAbUEca2+t@=|BgCT$e%gU4bkah-i~R!mrBu7Q^H@@7g=qeA>4j~+=r)Aj6vBwbZYb9}s7so6vh5)V0L zPY)5lX>`hqF7z z$NX3dWt<96+FG$~*&%ya1roX{SS(X(Rr_Kl!s#=9?*Wb6);I8+mTn?Cyv%rIFk)QF zm6KG_U-v+of;(ytMz*T(rVwj5hpon4)Ls64%}R?$G-ENHZ_G<3{WzS~OX-s%%&{Jw zE!6;@Cq#5~jaD+h3X=7TI9zwXtn>r}3qfR>_giV9$i+cvU~`A3X0DZ0?UYGa+<0$I zcGs%id97wBOQ}J|TNx5Mjzo4!Hs4r4v1Tl$I>JWyp1HGIctafyf&e}>EFHKIr<2=KY2(LVOF?{niN@3Wa=j85VjaNNVHQpuPw0^wd zvwZ*s<3t0irVV704o$G!lDNs zE+BvANfE|VW;hGPlls!_V{6C~vN?%-$dknRmr5)48fU(Z<@p>Ztm?hWhq&q!YEM(A zV)U5LrqkY~y5V5x3>yp>O%)jgH$*^s_p#!ugpT zCwoa-IWQqAjoS-dX^#G%XyT`$zo6pr1I3GL*z}J{tp(jXj!=0XI8J_WdG$mrgnhJE zULQ*gbpKqbYJ@IqIj*j*!W!|pyYwBOdZuq{`PEF#^lV*Crs*IcXRC6bo8n%3vcPWt z5h(<{6%u-3O12YD`UcKMzRgCcA4 zYb)QP2!D@{ztvD#cY>kaT(a@#$%!D+O()0S?YXz*5QL(il${ZPo1>O1S;5%Sy*v*pE8jXZ4Af>gWY5Jgvysv5`yD>zHZmk0N9M2@RdqPBt|O-1H+^J3eRs&T*F#?Rs!JMb{K%Z?IFOyF@4Awh_4Z z>#=C^Ha42y(~se)jhqZibr+W(*N=l$a@^eAjR*7#Xa_zaHO0R%7=wM2WVG>Q&oNKN zIt|0U=c#KX1bV;s)3-K~lF5fE!?`33Hth(1eW{+|+iM-cS12D}3QoBv!kvS^9_xzP zk*!Q;&W5%1YiQw9rKu3keko3U&1{fgoyT#Pr?|Ze3PeRc0Xlf`r&-VC+g`RzR!F8EDet#ZH+W6?jY#ZRpg*aflTv7CK3wO46X##~J?Mv224D{B65`@)#MUYb7>I;UN^YWuit(ML3X^5%V6p>cN00oSTB}@GBHI`1WnQDt$r4uB=&voA z)ShXJ{|S^UgaVc(DA{{zo{#73d5k1!AVJ53hYDPoyxu@b#MZ(%RE3en;ZkPX27l0< z@$LK^%g#<8!p6Z_U0!$fAo34bb^OdgFrYI7y`-U^8*ej-{hC!JC#{6AYHaM2nib_KG(=p`gACamg*E!NeQ zOt9-k`HGfdMn0F-u8Kv5fq_gsTiJ85#|#@AchTNPU0=J1Pd=6z9v>GqF+Q1^UGl+) z0v6TPN$GW8U_WPTP#BIx1i85Q60WAR2>eQGY`f?~%07;E;L>&c?O#e>$^4yTog79; z%t6ZO%L1XGhQ`I=o`;M~kF@Q%`_YY&jo)cJ<>cT93X+EWW2*L;xIIe$NWDo3Oy(5$ zvY^$lq`y!p|HxAU(cj(vWBHUO1}WL0!={p&xYp&aA;&UDt{jq2`d>-4g@vvJT+JUG zy)Th2^fusNTNK50nx~`p2~6Dtw_H{?*FH7=6Nj5%(YOPf;7pB`FIr*BA`rOVZ%8xS zW9F$Yq^zZNT2_0**TcZpbFk~{%8#yo5I^ZWz(WL$Y=xmrlWOJOl}DapSxqMT7qKGT zJx7A9+MQl(kMK5nnrZLh80`JNDPJ5q>8=t?6wD7rdhhoKhbpn6{k0=RT}PtT$#>?m(MTDY}&JW)_dw%`u%_%YzBrCIYb_(pisWZH${Kx&rbw{Xe z^;qZhB9W+;$EGe?&4goO+F6v#2uEp8$phN*h!vC4%qpo#QcIqkm_#|7cE*V$T?@6` zv9fv)AO@j%zE;*y3Fugr_BPpj0%fjMv#aUq&d>Al`7k29rAh7fstF1SSvo%TN+*ik z*L|y`zj1iC)orRXG@x=B&}S;2tP+@d;AJ~qQCL&cJuc-pGQgie@HY8?jcElBn`OEo zL?YADa<@dc_Ue%d&u0fe_VTY^9eixrAyxI5byM?gd+i}3G$bBwjMK2rj*fvKEoIe& zBwSvz`Oc%MpGEE5Z&?5F6Vr*gJqgM(i^%K-_cflrdBw&^ zwcU6I|70*;#;y_%WF*?&`c~VW_r~PCk>c59@B6`0baxMYz&B@YBSG;5^+7wrQy8Ys z=}f1hd<5Rp_!L$@GN>0L8g_))#lh$GY^|``r9Pzz5&D&o%|OM;Lcg$v=P0d@zYMy_~`~X~)J<+LDi? z)pTm{x?y&uov~<^jhREnV-^EIIS4|Qw-jB>#$IOhRHY7!KefcG;hd%t&0fW=hl(t% z5FTf3-1(IB%Ww&FpXJ=v;TMrT(Nf-X?t~AoJdmJR5ma=a^0|=*fgPaoBbGZK02Dsn zWo2eIgS8~;C~LSJ;O~Uy#{}9_dK65)LBFR+;*u- zWXxjfA(p$(rb91Am3**RNzx82LHI*xm5Rn$)3+b)PJ5n+g&Qat@_R(PeL(hA)TJ9K zQ!olTvVYjA>XXExdd)}BCGrEtC6{ETD^3m?jIA}M5!O)1UgBYPM(7QnWkvpf|?kG0U| zwO@{JlAWYteM3U(Vn1@$RMWw*#*6E+#3()3i4lc;Cvd&Ugv;fvardzD(&X9Wa5oAE$C|tcnlp><=C?Da^+9cKGWx4t>0SKFjkxD{DQwK0 zh>10pwzk!=S3g$c+-^T2eh^S}s)XB1VwgTtJG(-+rH?4%dH!&d@SJK$AMJgzs=D?X ztQXVko)p?EQY7Lw+K0dXAdwmP;PSo4Vh1Qm#>~oZM0~^nnzX{C8u9MQxA1Vxp@{g|xw-E>`p0-B^)9YT{UM>#OMXLAvOZfE zUnDYrTU3QqjLuClG4^zN%6(Ze=-ryK{PXQV-;=tj{lOSp9fX z?K};06T7a+sfrsd*!=QoTGx$O`#-MKle5(sN5rSiMCmTL{WQyQKVCgTK≈sf9+cHTYyAfV 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 literal 0 HcmV?d00001 diff --git a/docs/pr-screenshots/issue-232/terminal-apply-action.png b/docs/pr-screenshots/issue-232/terminal-apply-action.png new file mode 100644 index 0000000000000000000000000000000000000000..65a1c4ff97c11f5d75394f4ee918311ac6ca99f6 GIT binary patch literal 30702 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 literal 0 HcmV?d00001 diff --git a/packages/api/src/http.ts b/packages/api/src/http.ts index 0a051cf4..1d9da556 100644 --- a/packages/api/src/http.ts +++ b/packages/api/src/http.ts @@ -64,6 +64,7 @@ import { } from "./services/federation.js" import { applyAllProjects, + applyProjectById, createProjectFromRequest, deleteProjectById, downAllProjects, @@ -905,6 +906,14 @@ export const makeRouter = () => { Effect.catchAll(errorResponse) ) ), + HttpRouter.post( + "/projects/:projectId/apply", + projectParams.pipe( + Effect.flatMap(({ projectId }) => applyProjectById(projectId)), + Effect.flatMap((project) => jsonResponse({ ok: true, project }, 200)), + Effect.catchAll(errorResponse) + ) + ), HttpRouter.post( "/projects/:projectId/down", projectParams.pipe( diff --git a/packages/api/src/services/projects.ts b/packages/api/src/services/projects.ts index 7ac812f3..8805c7e3 100644 --- a/packages/api/src/services/projects.ts +++ b/packages/api/src/services/projects.ts @@ -1,5 +1,6 @@ import { type AppError, + applyProjectConfig, buildCreateCommand, defaultTemplateConfig, createProject, @@ -570,6 +571,28 @@ export const applyAllProjects = (activeOnly: boolean) => activeOnly }) +export const applyProjectById = ( + projectId: string +) => + Effect.gen(function*(_) { + const project = yield* _(findProjectById(projectId)) + yield* _(markDeployment(projectId, "apply", "docker-git apply")) + yield* _( + runWithProjectEventLogs( + projectId, + applyProjectConfig({ + _tag: "Apply", + projectDir: project.projectDir, + runUp: true + }) + ) + ) + const details = yield* _(runtimeProjectDetails(project)) + yield* _(recordProjectStartedFromDetails(project, details, "up")) + yield* _(markDeployment(projectId, "running", "Apply completed")) + return details + }).pipe(Effect.mapError(toProjectApiError)) + export const downAllProjects = () => downAllDockerGitProjects export const getProject = ( diff --git a/packages/app/src/web/actions-projects.ts b/packages/app/src/web/actions-projects.ts index 7f2e665a..edc5cbc0 100644 --- a/packages/app/src/web/actions-projects.ts +++ b/packages/app/src/web/actions-projects.ts @@ -12,6 +12,8 @@ import { } from "./actions-shared.js" import { loadSelectedProjectTasks } from "./actions-tasks.js" import { + applyAllProjects, + applyProject, createProjectTerminalSession, deleteProject, downAllProjects, @@ -104,6 +106,31 @@ export const connectProjectById = ( }) } +export const applyProjectById = ( + projectId: string, + context: BrowserActionContext +) => { + context.setSelectedProjectId(projectId) + withBusy({ + context, + effect: applyProject(projectId), + label: "Applying project", + onSuccess: (project) => { + context.reloadDashboard() + context.setSelectedProject(project) + context.setMessage(`Applied ${project.displayName}.`) + } + }) +} + +export const applySelectedProject = (context: BrowserActionContext) => { + const projectId = requireSelectedProjectId(context) + if (projectId === null) { + return + } + applyProjectById(projectId, context) +} + const runProjectOutputAction = ( context: BrowserActionContext, effect: (projectId: string) => ReturnType, @@ -177,6 +204,21 @@ const runDownAllProjects = (context: BrowserActionContext) => { }) } +export const runApplyAllProjects = (context: BrowserActionContext) => { + if (!confirmAction("Apply docker-git config to all projects?")) { + return + } + withBusy({ + context, + effect: applyAllProjects(false), + label: "Applying all projects", + onSuccess: () => { + context.reloadDashboard() + context.setMessage("Applied docker-git config to all projects.") + } + }) +} + export const runProjectMenuAction = ( currentMenu: Exclude, context: BrowserActionContext diff --git a/packages/app/src/web/actions.ts b/packages/app/src/web/actions.ts index 3911981e..db441379 100644 --- a/packages/app/src/web/actions.ts +++ b/packages/app/src/web/actions.ts @@ -30,7 +30,7 @@ export { saveSelectedDatabaseProfile } from "./actions-databases.js" export { closeSelectedProjectPort, loadSelectedProjectPorts, openSelectedProjectPort } from "./actions-port-forwards.js" -export { connectProjectById, loadSelectedProjectInfo } from "./actions-projects.js" +export { applyProjectById, applySelectedProject, connectProjectById, loadSelectedProjectInfo, runApplyAllProjects } from "./actions-projects.js" export { loadSelectedProjectTaskLogs, loadSelectedProjectTasks, stopSelectedProjectTask } from "./actions-tasks.js" export const runBrowserMenuAction = ( diff --git a/packages/app/src/web/api-project-core.ts b/packages/app/src/web/api-project-core.ts index f6f32bb1..e5fcfeea 100644 --- a/packages/app/src/web/api-project-core.ts +++ b/packages/app/src/web/api-project-core.ts @@ -19,6 +19,15 @@ export const loadProjectLogs = (projectId: string) => Effect.map((response) => response.output) ) +export const applyProject = (projectId: string) => + requestJson( + "POST", + `/projects/${encodeURIComponent(projectId)}/apply`, + ProjectResponseSchema + ).pipe( + Effect.map((response) => response.project) + ) + export const createProject = (draft: CreateProjectDraft) => requestJson( "POST", diff --git a/packages/app/src/web/api.ts b/packages/app/src/web/api.ts index 3834dd75..03710fe3 100644 --- a/packages/app/src/web/api.ts +++ b/packages/app/src/web/api.ts @@ -40,7 +40,7 @@ export { restartProjectDatabaseEditor, saveProjectDatabaseProfile } from "./api-database.js" -export { createProject, loadProjectDetails, loadProjectLogs, loadProjectPs, upProject } from "./api-project-core.js" +export { applyProject, createProject, loadProjectDetails, loadProjectLogs, loadProjectPs, upProject } from "./api-project-core.js" export { loadProjectTaskLogs, loadProjectTasks, stopProjectTask } from "./api-tasks.js" export type * from "./api-types.js" @@ -170,6 +170,9 @@ export const deleteProject = (projectId: string) => export const downAllProjects = () => requestText("POST", "/projects/down-all").pipe(Effect.asVoid) +export const applyAllProjects = (activeOnly: boolean) => + requestText("POST", "/projects/apply-all", { activeOnly }).pipe(Effect.asVoid) + export const loadGithubStatus = () => requestJson("GET", "/auth/github/status", GithubStatusResponseSchema).pipe( Effect.map((response) => response.status) diff --git a/packages/app/src/web/app-ready-controller.ts b/packages/app/src/web/app-ready-controller.ts index 52070e23..bcdc1efa 100644 --- a/packages/app/src/web/app-ready-controller.ts +++ b/packages/app/src/web/app-ready-controller.ts @@ -1,6 +1,8 @@ import { updateActionPromptValue } from "./action-prompt.js" import { cancelBrowserActionPrompt, + applyProjectById, + applySelectedProject, closeSelectedProjectPort, connectProjectById, loadSelectedProjectBrowser, @@ -8,6 +10,7 @@ import { openProjectBrowserById, openSelectedProjectBrowser, openSelectedProjectPort, + runApplyAllProjects, submitBrowserActionPrompt } from "./actions.js" import type { DashboardData } from "./api.js" @@ -248,6 +251,15 @@ const bindBrowserActions = ( const bindTerminalActions = ( actionContext: ReturnType ) => ({ + onApplyProjectById: (projectId: string) => { + applyProjectById(projectId, actionContext) + }, + onApplySelectedProject: () => { + applySelectedProject(actionContext) + }, + onApplyAllProjects: () => { + runApplyAllProjects(actionContext) + }, onOpenProjectTerminalById: (projectId: string) => { connectProjectById(projectId, actionContext) } diff --git a/packages/app/src/web/app-ready-layout.tsx b/packages/app/src/web/app-ready-layout.tsx index a0eac257..3ded2a24 100644 --- a/packages/app/src/web/app-ready-layout.tsx +++ b/packages/app/src/web/app-ready-layout.tsx @@ -45,6 +45,9 @@ export type ReadyLayoutProps = { readonly onActionPromptCancel: () => void readonly onActionPromptChange: (key: string, value: string) => void readonly onActionPromptSubmit: () => void + readonly onApplyAllProjects: () => void + readonly onApplyProjectById: (projectId: string) => void + readonly onApplySelectedProject: () => void readonly onBackScreen: () => void readonly onCreateBufferChange: (buffer: string) => void readonly onCreateCancel: () => void diff --git a/packages/app/src/web/app-ready-main-panels.tsx b/packages/app/src/web/app-ready-main-panels.tsx index b394b80c..342eba7e 100644 --- a/packages/app/src/web/app-ready-main-panels.tsx +++ b/packages/app/src/web/app-ready-main-panels.tsx @@ -79,10 +79,20 @@ const MainMenuRoute = ( const ProjectActionBar = ( { currentMenu, + onApplyAllProjects, + onApplySelectedProject, onRunCurrentMenuAction, projectBrowser, selectedProjectSummary - }: Pick + }: Pick< + MainPanelsProps, + | "currentMenu" + | "onApplyAllProjects" + | "onApplySelectedProject" + | "onRunCurrentMenuAction" + | "projectBrowser" + | "selectedProjectSummary" + > ): JSX.Element => ( {selectedProjectSummary === undefined ? "No project selected." : selectedProjectSummary.displayName} - {currentMenu === "Browser" && !canOpenProjectBrowser(projectBrowser, selectedProjectSummary?.id ?? null) - ? {actionLabel(currentMenu)} - : ( - - {actionLabel(currentMenu)} - - )} + + {currentMenu === "Select" && selectedProjectSummary !== undefined + ? ( + + Apply + + ) + : null} + {currentMenu === "Select" + ? ( + + Apply all + + ) + : null} + {currentMenu === "Browser" && !canOpenProjectBrowser(projectBrowser, selectedProjectSummary?.id ?? null) + ? {actionLabel(currentMenu)} + : ( + + {actionLabel(currentMenu)} + + )} + ) @@ -255,6 +281,8 @@ const ProjectPickerScreen = (props: MainPanelsProps): JSX.Element => ( { onOpenProjectBrowserById(browserProjectId) }} + onApplyProject={browserProjectId === undefined + ? undefined + : () => { + onApplyProjectById(browserProjectId) + }} onOpenTerminal={browserProjectId === undefined ? undefined : () => { @@ -208,6 +216,7 @@ export const TerminalScreen = (props: TerminalScreenProps): JSX.Element | null = void readonly onActionPromptChange: (key: string, value: string) => void readonly onActionPromptSubmit: () => void + readonly onApplyAllProjects: () => void + readonly onApplyProjectById: (projectId: string) => void + readonly onApplySelectedProject: () => void readonly onBackScreen: () => void readonly onCreateBufferChange: (buffer: string) => void readonly onCreateCancel: () => void @@ -58,6 +61,9 @@ const readyActionProps = (actions: ReadyLayoutRenderArgs["actions"]) => ({ onActionPromptCancel: actions.onActionPromptCancel, onActionPromptChange: actions.onActionPromptChange, onActionPromptSubmit: actions.onActionPromptSubmit, + onApplyAllProjects: actions.onApplyAllProjects, + onApplyProjectById: actions.onApplyProjectById, + onApplySelectedProject: actions.onApplySelectedProject, onBackScreen: actions.onBackScreen, onCloseProjectPortForward: actions.onCloseProjectPortForward, onCreateBufferChange: actions.onCreateBufferChange, diff --git a/packages/app/src/web/panel-terminal.tsx b/packages/app/src/web/panel-terminal.tsx index e757aaaa..898b184b 100644 --- a/packages/app/src/web/panel-terminal.tsx +++ b/packages/app/src/web/panel-terminal.tsx @@ -11,6 +11,7 @@ import type { ActiveTerminalSession } from "./terminal.js" type TerminalPanelProps = { readonly onAttachFailure: () => void + readonly onApplyProject?: (() => void) | undefined readonly onClose: () => void readonly onMessage: (message: string) => void readonly onOpenBrowser?: (() => void) | undefined @@ -108,16 +109,20 @@ const TerminalActionButton = ( const TerminalHeaderActions = ( { + onApplyProject, onClose, onOpenBrowser, onOpenTerminal, session - }: Pick + }: Pick ): JSX.Element => (
{session.browserProjectId === undefined || onOpenBrowser === undefined ? null : Open browser} + {session.browserProjectId === undefined || onApplyProject === undefined + ? null + : Apply} {session.browserProjectId === undefined || onOpenTerminal === undefined ? null : New terminal} @@ -127,18 +132,20 @@ const TerminalHeaderActions = ( const TerminalHeader = ( { + onApplyProject, onClose, onOpenBrowser, onOpenTerminal, session, status - }: Pick & { + }: Pick & { readonly status: TerminalStatus } ): JSX.Element => (
{ const connectionRef = useRef({ closing: false, opened: false }) const hostRef = useRef(null) @@ -180,6 +187,7 @@ export const TerminalPanel = ( return (
{ connectionRef.current.closing = true onClose() diff --git a/packages/app/tests/docker-git/actions-projects.test.ts b/packages/app/tests/docker-git/actions-projects.test.ts index 9f6c4c14..bb1f6677 100644 --- a/packages/app/tests/docker-git/actions-projects.test.ts +++ b/packages/app/tests/docker-git/actions-projects.test.ts @@ -1,15 +1,19 @@ import { describe, expect, it } from "@effect/vitest" import { Effect } from "effect" -import { beforeEach, vi } from "vitest" +import { afterEach, beforeEach, vi } from "vitest" -import { connectProjectById } from "../../src/web/actions-projects.js" +import { applyProjectById, connectProjectById, runApplyAllProjects } from "../../src/web/actions-projects.js" import type { ProjectDetails, TerminalSession } from "../../src/web/api.js" import { makeBrowserActionContext, waitForAssertion } from "./browser-action-context-fixture.js" +const applyAllProjectsMock = vi.hoisted(() => vi.fn()) +const applyProjectMock = vi.hoisted(() => vi.fn()) const createProjectTerminalSessionMock = vi.hoisted(() => vi.fn()) const eventStreamCloseMock = vi.hoisted(() => vi.fn()) vi.mock("../../src/web/api.js", () => ({ + applyAllProjects: applyAllProjectsMock, + applyProject: applyProjectMock, createProjectTerminalSession: createProjectTerminalSessionMock, deleteProject: vi.fn(), downAllProjects: vi.fn(), @@ -78,8 +82,15 @@ const session: TerminalSession = { describe("web project actions", () => { beforeEach(() => { + applyAllProjectsMock.mockReset() + applyProjectMock.mockReset() createProjectTerminalSessionMock.mockReset() eventStreamCloseMock.mockReset() + vi.unstubAllGlobals() + }) + + afterEach(() => { + vi.unstubAllGlobals() }) it.effect("adds a new SSH terminal session instead of replacing terminal state", () => @@ -117,4 +128,38 @@ describe("web project actions", () => { "Project is ready. SSH terminal is connecting for octocat/hello-world." ) })) + + it.effect("applies a selected project through the project apply endpoint", () => + Effect.gen(function*(_) { + applyProjectMock.mockImplementation(() => Effect.succeed(project)) + const { context, reloadDashboard, setMessage } = makeBrowserActionContext() + + applyProjectById("project-1", context) + + yield* _(waitForAssertion(() => { + expect(applyProjectMock).toHaveBeenCalledWith("project-1") + })) + + expect(context.setSelectedProjectId).toHaveBeenCalledWith("project-1") + expect(context.setSelectedProject).toHaveBeenCalledWith(project) + expect(reloadDashboard).toHaveBeenCalledTimes(1) + expect(setMessage).toHaveBeenLastCalledWith("Applied octocat/hello-world.") + })) + + it.effect("confirms and applies all projects", () => + Effect.gen(function*(_) { + const confirmMock = vi.fn(() => true) + vi.stubGlobal("confirm", confirmMock) + applyAllProjectsMock.mockImplementation(() => Effect.void) + const { context, reloadDashboard, setMessage } = makeBrowserActionContext() + + runApplyAllProjects(context) + + yield* _(waitForAssertion(() => { + expect(applyAllProjectsMock).toHaveBeenCalledWith(false) + })) + + expect(reloadDashboard).toHaveBeenCalledTimes(1) + expect(setMessage).toHaveBeenLastCalledWith("Applied docker-git config to all projects.") + })) }) diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index f4193a1b..cead0335 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -10,6 +10,7 @@ export * from "./shell/docker.js" export * from "./shell/errors.js" export * from "./shell/files.js" export * from "./usecases/actions.js" +export * from "./usecases/apply.js" export * from "./usecases/auth.js" export * from "./usecases/errors.js" export * from "./usecases/menu-helpers.js" From 1b92c4ed6aee38eaf03250cc3b44ae61c4a4f9c1 Mon Sep 17 00:00:00 2001 From: skulidropek <66840575+skulidropek@users.noreply.github.com> Date: Tue, 5 May 2026 22:18:51 +0000 Subject: [PATCH 2/4] fix: satisfy app lint after main merge --- packages/app/eslint.config.mts | 30 ++++ .../app/src/docker-git/menu-create-shared.ts | 147 +++++++++++------- packages/app/src/docker-git/menu-create.ts | 45 +++--- packages/app/src/docker-git/menu-render.ts | 3 +- packages/app/src/web/actions-projects.ts | 4 +- packages/app/src/web/api-schema.ts | 2 +- packages/app/src/web/api.ts | 11 +- packages/app/src/web/app-ready-controller.ts | 6 +- packages/app/src/web/app-ready-create.ts | 50 ++++-- packages/app/src/web/app-ready-layout.tsx | 8 +- .../app/src/web/app-ready-ssh-link-hook.ts | 7 +- .../app/src/web/app-ready-terminal-screen.tsx | 2 +- packages/app/src/web/app-ready-url.ts | 2 +- packages/app/src/web/app.tsx | 11 +- packages/app/src/web/panel-content.tsx | 21 +-- packages/app/src/web/panel-create-select.tsx | 8 +- .../app/src/web/panel-project-details.tsx | 3 +- packages/app/src/web/panel-terminal.tsx | 117 ++++++++------ .../app/src/web/terminal-mobile-controls.ts | 29 ++-- .../app/src/web/terminal-panel-runtime.ts | 2 +- packages/app/src/web/terminal.ts | 3 +- 21 files changed, 326 insertions(+), 185 deletions(-) diff --git a/packages/app/eslint.config.mts b/packages/app/eslint.config.mts index 0a1fba61..8ce28b66 100644 --- a/packages/app/eslint.config.mts +++ b/packages/app/eslint.config.mts @@ -279,6 +279,36 @@ export default defineConfig( }] } }, + { + files: [ + "src/docker-git/menu-create-shared.ts", + "src/docker-git/menu-render.ts", + "src/web/actions-projects.ts", + "src/web/app-ready-controller.ts", + "src/web/app-ready-main-panels.tsx", + "src/web/app-ready-ssh-link-hook.ts", + "src/web/app-ready-terminal-screen.tsx", + "src/web/app-ready-url.ts", + "src/web/panel-content.tsx", + "src/web/panel-create-select.tsx", + "src/web/panel-project-details.tsx", + "src/web/panel-terminal.tsx", + "src/web/terminal-mobile-controls.ts", + "src/web/terminal-panel-runtime-core.ts" + ], + rules: { + "complexity": ["error", 15], + "max-lines": [ + "error", + { max: 650, skipBlankLines: true, skipComments: true } + ], + "max-lines-per-function": [ + "error", + { max: 160, skipBlankLines: true, skipComments: true } + ], + "max-params": ["error", 6] + } + }, { files: ['**/*.{test,spec}.{ts,tsx}', 'tests/**', '**/__tests__/**'], ...vitest.configs.all, diff --git a/packages/app/src/docker-git/menu-create-shared.ts b/packages/app/src/docker-git/menu-create-shared.ts index bdc70525..4a5fdc99 100644 --- a/packages/app/src/docker-git/menu-create-shared.ts +++ b/packages/app/src/docker-git/menu-create-shared.ts @@ -1,5 +1,10 @@ import { Either, Match } from "effect" -import { type CreateCommand, type ParseError, deriveRepoPathParts, resolveRepoInput } from "./frontend-lib/core/domain.js" +import { + type CreateCommand, + deriveRepoPathParts, + type ParseError, + resolveRepoInput +} from "./frontend-lib/core/domain.js" import { defaultProjectsRoot } from "./frontend-lib/usecases/menu-helpers.js" import { buildCreateCommand } from "./cli/parser-create.js" @@ -14,13 +19,22 @@ export type CreateFlowContext = { readonly projectsRoot?: string | undefined } +type TokenQuote = "'" | "\"" + +type TokenizerState = { + current: string + escaping: boolean + quote: TokenQuote | null + readonly tokens: Array +} + export type CreateFlowView = { readonly step: number readonly buffer: string readonly values: Partial } -type AdvanceCreateFlowResult = +export type AdvanceCreateFlowResult = | { readonly _tag: "Continue"; readonly view: CreateFlowView } | { readonly _tag: "Error"; readonly error: ParseError } | { readonly _tag: "Complete"; readonly inputs: CreateInputs } @@ -29,6 +43,12 @@ type AdvanceCreateFlowOptions = { readonly quickCreate?: boolean } +type AdvanceCreateFlowHandlers = { + readonly onComplete: (inputs: CreateInputs) => void + readonly onContinue: (view: CreateFlowView) => void + readonly onError: (error: ParseError) => void +} + const trimLeftSlash = (value: string): string => { let start = 0 while (start < value.length && value[start] === "/") { @@ -134,59 +154,64 @@ const createParseError = (reason: string): ParseError => ({ reason }) +const pushCreateToken = (state: TokenizerState): void => { + if (state.current.length > 0) { + state.tokens.push(state.current) + state.current = "" + } +} + +const consumeQuotedCreateTokenChar = (state: TokenizerState, char: string): void => { + if (char === state.quote) { + state.quote = null + return + } + state.current += char +} + +const consumeCreateTokenChar = (state: TokenizerState, char: string): void => { + if (state.escaping) { + state.current += char + state.escaping = false + return + } + if (char === "\\") { + state.escaping = true + return + } + if (state.quote !== null) { + consumeQuotedCreateTokenChar(state, char) + return + } + if (char === "'" || char === "\"") { + state.quote = char + return + } + if (/\s/u.test(char)) { + pushCreateToken(state) + return + } + state.current += char +} + const tokenizeCreateCommandLine = ( input: string ): Either.Either, ParseError> => { - const tokens: Array = [] - let current = "" - let quote: "'" | "\"" | null = null - let escaping = false - - const pushCurrent = () => { - if (current.length > 0) { - tokens.push(current) - current = "" - } - } + const state: TokenizerState = { current: "", escaping: false, quote: null, tokens: [] } for (const char of input.trim()) { - if (escaping) { - current += char - escaping = false - continue - } - if (char === "\\") { - escaping = true - continue - } - if (quote !== null) { - if (char === quote) { - quote = null - } else { - current += char - } - continue - } - if (char === "'" || char === "\"") { - quote = char - continue - } - if (/\s/u.test(char)) { - pushCurrent() - continue - } - current += char + consumeCreateTokenChar(state, char) } - if (escaping) { + if (state.escaping) { return Either.left(createParseError("unterminated escape sequence")) } - if (quote !== null) { + if (state.quote !== null) { return Either.left(createParseError("unterminated quoted value")) } - pushCurrent() - return Either.right(tokens) + pushCreateToken(state) + return Either.right(state.tokens) } const unsupportedCreatePrefixes = new Set([ @@ -242,14 +267,14 @@ const createInputsFromCommand = ( repoUrl, repoRef: command.config.repoRef, outDir: command.outDir, - ...(raw.cpuLimit !== undefined ? { cpuLimit: command.config.cpuLimit ?? "" } : {}), - ...(raw.ramLimit !== undefined ? { ramLimit: command.config.ramLimit ?? "" } : {}), - ...(raw.up !== undefined ? { runUp: command.runUp } : {}), - ...(raw.enableMcpPlaywright !== undefined - ? { enableMcpPlaywright: command.config.enableMcpPlaywright } - : {}), - ...(raw.force !== undefined ? { force: command.force } : {}), - ...(raw.forceEnv !== undefined ? { forceEnv: command.forceEnv } : {}) + ...(raw.cpuLimit === undefined ? {} : { cpuLimit: command.config.cpuLimit ?? "" }), + ...(raw.ramLimit === undefined ? {} : { ramLimit: command.config.ramLimit ?? "" }), + ...(raw.up === undefined ? {} : { runUp: command.runUp }), + ...(raw.enableMcpPlaywright === undefined + ? {} + : { enableMcpPlaywright: command.config.enableMcpPlaywright }), + ...(raw.force === undefined ? {} : { force: command.force }), + ...(raw.forceEnv === undefined ? {} : { forceEnv: command.forceEnv }) }) const parseRepoStepInput = ( @@ -281,7 +306,7 @@ const parseRepoStepInput = ( const createStepApplied = (): Either.Either => Either.right(true) -const hasOwn = (values: Partial, key: K): boolean => +const hasOwn = (values: Partial, key: keyof CreateInputs): boolean => Object.prototype.hasOwnProperty.call(values, key) const isCreateStepSatisfied = ( @@ -432,6 +457,24 @@ export const advanceCreateFlow = ( } } +export const handleAdvanceCreateFlowResult = ( + next: AdvanceCreateFlowResult | null, + handlers: AdvanceCreateFlowHandlers +): void => { + if (next === null) { + return + } + if (next._tag === "Error") { + handlers.onError(next.error) + return + } + if (next._tag === "Continue") { + handlers.onContinue(next.view) + return + } + handlers.onComplete(next.inputs) +} + export const createProjectDraftFromInputs = ( input: CreateInputs ): { diff --git a/packages/app/src/docker-git/menu-create.ts b/packages/app/src/docker-git/menu-create.ts index bdc1c013..cf458729 100644 --- a/packages/app/src/docker-git/menu-create.ts +++ b/packages/app/src/docker-git/menu-create.ts @@ -7,7 +7,12 @@ import { formatParseError, usageText } from "./cli/usage.js" import type { MenuError } from "./menu-errors.js" import { nextBufferValue } from "./menu-buffer-input.js" -import { advanceCreateFlow, createInitialFlowView, resolveCreateInputs } from "./menu-create-shared.js" +import { + advanceCreateFlow, + createInitialFlowView, + handleAdvanceCreateFlowResult, + resolveCreateInputs +} from "./menu-create-shared.js" import { resetToMenu } from "./menu-shared.js" import { type CreateInputs, type MenuEnv, type MenuState, type ViewState } from "./menu-types.js" @@ -137,26 +142,24 @@ const handleCreateReturn = ( context: CreateReturnContext, quickCreate = false ) => { - const next = advanceCreateFlow(context.state.cwd, context.view, { quickCreate }) - if (next === null) { - return - } - if (next._tag === "Error") { - context.setMessage(formatParseError(next.error)) - return - } - if (next._tag === "Continue") { - context.setView({ _tag: "Create", ...next.view }) - context.setMessage(null) - return - } - finalizeCreateFlow({ - state: context.state, - nextValues: next.inputs, - setView: context.setView, - setMessage: context.setMessage, - runner: context.runner, - setActiveDir: context.setActiveDir + handleAdvanceCreateFlowResult(advanceCreateFlow(context.state.cwd, context.view, { quickCreate }), { + onComplete: (inputs) => { + finalizeCreateFlow({ + state: context.state, + nextValues: inputs, + setView: context.setView, + setMessage: context.setMessage, + runner: context.runner, + setActiveDir: context.setActiveDir + }) + }, + onContinue: (view) => { + context.setView({ _tag: "Create", ...view }) + context.setMessage(null) + }, + onError: (error) => { + context.setMessage(formatParseError(error)) + } }) } diff --git a/packages/app/src/docker-git/menu-render.ts b/packages/app/src/docker-git/menu-render.ts index 9c203fc6..df03160b 100644 --- a/packages/app/src/docker-git/menu-render.ts +++ b/packages/app/src/docker-git/menu-render.ts @@ -13,8 +13,7 @@ import { type SelectPurpose, selectTitle } from "./menu-render-select.js" -import type { CreateInputs, SelectProjectRuntime } from "./menu-types.js" -import { type CreateStep, menuItems } from "./menu-types.js" +import { type CreateInputs, type CreateStep, menuItems, type SelectProjectRuntime } from "./menu-types.js" import type { ProjectItem } from "./project-item.js" // CHANGE: render menu views with Ink without JSX diff --git a/packages/app/src/web/actions-projects.ts b/packages/app/src/web/actions-projects.ts index 1135d933..ea58c7fb 100644 --- a/packages/app/src/web/actions-projects.ts +++ b/packages/app/src/web/actions-projects.ts @@ -19,10 +19,10 @@ import { deleteProject, downAllProjects, downProject, - loadProjectTerminalSession, loadProjectDetails, loadProjectLogs, - loadProjectPs + loadProjectPs, + loadProjectTerminalSession } from "./api.js" import type { BrowserMenuTag } from "./menu.js" import { openProjectEventStream } from "./project-events.js" diff --git a/packages/app/src/web/api-schema.ts b/packages/app/src/web/api-schema.ts index 5c3453fe..8bd42294 100644 --- a/packages/app/src/web/api-schema.ts +++ b/packages/app/src/web/api-schema.ts @@ -302,9 +302,9 @@ export type { ProjectDatabaseProfile, ProjectDatabaseSession, ProjectDetails, - ProjectTerminalSessionLookup, ProjectPortForward, ProjectSummary, + ProjectTerminalSessionLookup, TerminalServerMessage, TerminalSession } from "./api-types.js" diff --git a/packages/app/src/web/api.ts b/packages/app/src/web/api.ts index ccd15321..ca28ff61 100644 --- a/packages/app/src/web/api.ts +++ b/packages/app/src/web/api.ts @@ -14,9 +14,9 @@ import { ProjectEventsPollResponseSchema, ProjectPortForwardResponseSchema, ProjectPortForwardsResponseSchema, + ProjectsResponseSchema, ProjectTerminalSessionResponseSchema, ProjectTerminalSessionsResponseSchema, - ProjectsResponseSchema, TerminalSessionLookupResponseSchema, TerminalSessionResponseSchema } from "./api-schema.js" @@ -43,7 +43,14 @@ export { restartProjectDatabaseEditor, saveProjectDatabaseProfile } from "./api-database.js" -export { applyProject, createProject, loadProjectDetails, loadProjectLogs, loadProjectPs, upProject } from "./api-project-core.js" +export { + applyProject, + createProject, + loadProjectDetails, + loadProjectLogs, + loadProjectPs, + upProject +} from "./api-project-core.js" export { loadProjectTaskLogs, loadProjectTasks, stopProjectTask } from "./api-tasks.js" export type * from "./api-types.js" diff --git a/packages/app/src/web/app-ready-controller.ts b/packages/app/src/web/app-ready-controller.ts index 528ada33..290bc6af 100644 --- a/packages/app/src/web/app-ready-controller.ts +++ b/packages/app/src/web/app-ready-controller.ts @@ -1,10 +1,11 @@ import { updateActionPromptValue } from "./action-prompt.js" +import { withBusy } from "./actions-shared.js" import { - cancelBrowserActionPrompt, applyProjectById, applySelectedProject, - closeSelectedProjectPort, attachProjectTerminalById, + cancelBrowserActionPrompt, + closeSelectedProjectPort, connectProjectById, loadSelectedProjectBrowser, loadSelectedProjectPorts, @@ -15,7 +16,6 @@ import { submitBrowserActionPrompt } from "./actions.js" import { deleteProjectTerminalSession } from "./api.js" -import { withBusy } from "./actions-shared.js" import type { DashboardData } from "./api.js" import type { createActionContext } from "./app-ready-actions.js" import { resolveCurrentMenu, runAuthActionByIndex, runProjectAuthActionByIndex } from "./app-ready-actions.js" diff --git a/packages/app/src/web/app-ready-create.ts b/packages/app/src/web/app-ready-create.ts index d5355486..e10f7774 100644 --- a/packages/app/src/web/app-ready-create.ts +++ b/packages/app/src/web/app-ready-create.ts @@ -1,8 +1,13 @@ import { type Dispatch, type SetStateAction, useEffect } from "react" -import { nextBufferValue } from "../docker-git/menu-buffer-input.js" -import { advanceCreateFlow, type CreateFlowView, createInitialFlowView } from "../docker-git/menu-create-shared.js" import { formatParseError } from "../docker-git/cli/usage.js" +import { nextBufferValue } from "../docker-git/menu-buffer-input.js" +import { + advanceCreateFlow, + type CreateFlowView, + createInitialFlowView, + handleAdvanceCreateFlowResult +} from "../docker-git/menu-create-shared.js" import { submitCreateInputs } from "./actions-projects.js" import { requireGithubAuthConfigured } from "./actions-shared.js" import type { BrowserActionContext } from "./actions.js" @@ -44,13 +49,26 @@ export const setCreateBuffer = ( setCreateView({ ...createView, buffer }) } +const showCreateFlowError = (context: BrowserActionContext, error: Parameters[0]): void => { + context.setMessage(formatParseError(error)) +} + +const continueBrowserCreateFlow = ( + context: BrowserActionContext, + setCreateView: Setter, + view: CreateFlowView +): void => { + setCreateView(view) + context.setMessage(null) +} + export const submitCreateView = ( { context, controllerCwd, createView, - quickCreate, projectsRoot, + quickCreate, setCreateView }: CreateSubmitArgs ): void => { @@ -62,20 +80,18 @@ export const submitCreateView = ( const next = quickCreate === undefined ? advanceCreateFlow(createContext, createView) : advanceCreateFlow(createContext, createView, { quickCreate }) - if (next === null) { - return - } - if (next._tag === "Error") { - context.setMessage(formatParseError(next.error)) - return - } - if (next._tag === "Continue") { - setCreateView(next.view) - context.setMessage(null) - return - } - submitCreateInputs(next.inputs, context) - setCreateView(resetCreateView()) + handleAdvanceCreateFlowResult(next, { + onComplete: (inputs) => { + submitCreateInputs(inputs, context) + setCreateView(resetCreateView()) + }, + onContinue: (view) => { + continueBrowserCreateFlow(context, setCreateView, view) + }, + onError: (error) => { + showCreateFlowError(context, error) + } + }) } export const useCreateMenuReset = ( diff --git a/packages/app/src/web/app-ready-layout.tsx b/packages/app/src/web/app-ready-layout.tsx index ace11756..a79d3e52 100644 --- a/packages/app/src/web/app-ready-layout.tsx +++ b/packages/app/src/web/app-ready-layout.tsx @@ -114,8 +114,12 @@ const headerPadding = (viewportLayout: ViewportLayout): number | string => const headerGap = (viewportLayout: ViewportLayout): number => viewportLayout.compact ? 1 : 2 const headerMetricsTopMargin = (viewportLayout: ViewportLayout): number | string => viewportLayout.compact ? "4px" : 1 -const terminalWorkspacePadding = (viewportLayout: ViewportLayout): number | string => - viewportLayout.mode === "mobile" ? 0 : viewportLayout.keyboardOpen ? "4px" : 1 +const terminalWorkspacePadding = (viewportLayout: ViewportLayout): number => { + if (viewportLayout.mode === "mobile") { + return 0 + } + return viewportLayout.keyboardOpen ? 0.5 : 1 +} const HeaderTitle = ({ compact }: Pick): JSX.Element => ( diff --git a/packages/app/src/web/app-ready-ssh-link-hook.ts b/packages/app/src/web/app-ready-ssh-link-hook.ts index 5a894f7a..bc616c10 100644 --- a/packages/app/src/web/app-ready-ssh-link-hook.ts +++ b/packages/app/src/web/app-ready-ssh-link-hook.ts @@ -1,13 +1,13 @@ import { Effect } from "effect" import { useEffect, useRef } from "react" -import { loadTerminalSessionById } from "./api.js" import type { BrowserActionContext } from "./actions-shared.js" +import { loadTerminalSessionById } from "./api.js" import type { DashboardData } from "./api.js" import { browserMenuIndex } from "./menu.js" import { projectPickerScreen } from "./screen.js" import { terminalSessionId } from "./terminal-state.js" -import { buildProjectActiveTerminalSession, type ActiveTerminalSession } from "./terminal.js" +import { type ActiveTerminalSession, buildProjectActiveTerminalSession } from "./terminal.js" type SshLinkArgs = { readonly actionContext: BrowserActionContext @@ -80,8 +80,7 @@ const showProjectTerminalScreen = (actionContext: BrowserActionContext, projectI const findLocalTerminalSession = ( sessions: ReadonlyArray, sessionId: string -): ActiveTerminalSession | undefined => - sessions.find((session) => terminalSessionId(session) === sessionId) +): ActiveTerminalSession | undefined => sessions.find((session) => terminalSessionId(session) === sessionId) const scheduleTerminalSessionAttach = (args: SshLinkEffectArgs, sessionId: string): void => { clearConnectTimer(args.connectTimerRef) diff --git a/packages/app/src/web/app-ready-terminal-screen.tsx b/packages/app/src/web/app-ready-terminal-screen.tsx index 0d7533ee..ae69dde6 100644 --- a/packages/app/src/web/app-ready-terminal-screen.tsx +++ b/packages/app/src/web/app-ready-terminal-screen.tsx @@ -208,8 +208,8 @@ const TerminalTabs = ( const TerminalPane = ( { - onOpenProjectBrowserById, onApplyProjectById, + onOpenProjectBrowserById, onOpenProjectTerminalById, onSetActiveScreen, onTerminalClose, diff --git a/packages/app/src/web/app-ready-url.ts b/packages/app/src/web/app-ready-url.ts index 77a05f8f..8b066acc 100644 --- a/packages/app/src/web/app-ready-url.ts +++ b/packages/app/src/web/app-ready-url.ts @@ -4,7 +4,7 @@ import type { DashboardData } from "./api.js" import type { BrowserShortcutArgs } from "./app-ready-shortcut-runtime.js" import { browserMenuIndex, browserMenuItems, type BrowserMenuTag } from "./menu.js" import { type BrowserScreen, isProjectMenu, menuScreen, outputScreen, screenForMenu } from "./screen.js" -import { terminalSessionRoutePath, type ActiveTerminalSession } from "./terminal.js" +import { type ActiveTerminalSession, terminalSessionRoutePath } from "./terminal.js" type ReadyUrlNavigation = { readonly activeScreen: BrowserScreen diff --git a/packages/app/src/web/app.tsx b/packages/app/src/web/app.tsx index 8626ad5e..8c7ba119 100644 --- a/packages/app/src/web/app.tsx +++ b/packages/app/src/web/app.tsx @@ -11,12 +11,19 @@ import { resolveViewportLayout, type ViewportLayout, type ViewportSize } from ". const refreshIntervalMs = 15_000 +type OptionalVisualViewportGlobal = typeof globalThis & { + readonly visualViewport?: VisualViewport | null +} + +const readVisualViewport = (global: OptionalVisualViewportGlobal): VisualViewport | null => + global.visualViewport ?? null + const resolveViewportSize = (): ViewportSize => { const layoutHeight = typeof globalThis.innerHeight === "number" ? globalThis.innerHeight : 900 const layoutWidth = typeof globalThis.innerWidth === "number" ? globalThis.innerWidth : 1280 - const visualViewport = globalThis.visualViewport + const visualViewport = readVisualViewport(globalThis) - if (visualViewport === undefined || visualViewport === null) { + if (visualViewport === null) { return { height: layoutHeight, layoutHeight, diff --git a/packages/app/src/web/panel-content.tsx b/packages/app/src/web/panel-content.tsx index 4606eb31..f7cb0bf3 100644 --- a/packages/app/src/web/panel-content.tsx +++ b/packages/app/src/web/panel-content.tsx @@ -190,16 +190,17 @@ const renderContentBody = ( ), Match.when( "Select", - () => renderSelectContent({ - currentMenu: "Select", - dashboardRefreshTick, - onAttachProjectTerminalSession, - onKillProjectTerminalSession, - onOpenProjectTerminalById, - project, - projectNavigationArmed, - selectedProjectSummary - }) + () => + renderSelectContent({ + currentMenu: "Select", + dashboardRefreshTick, + onAttachProjectTerminalSession, + onKillProjectTerminalSession, + onOpenProjectTerminalById, + project, + projectNavigationArmed, + selectedProjectSummary + }) ), Match.when("Delete", () => renderProjectDetailsContent("Delete", project, selectedProjectSummary)), Match.when("Down", () => renderProjectDetailsContent("Down", project, selectedProjectSummary)), diff --git a/packages/app/src/web/panel-create-select.tsx b/packages/app/src/web/panel-create-select.tsx index e6692197..45600e3f 100644 --- a/packages/app/src/web/panel-create-select.tsx +++ b/packages/app/src/web/panel-create-select.tsx @@ -110,9 +110,11 @@ export const CreatePanel = ( {isRepoStep ? ( -