From d005a73bdfeb230d7d02cc7787e1b6ed349636b6 Mon Sep 17 00:00:00 2001 From: eduardo aleixo Date: Wed, 19 Jan 2022 17:40:55 -0300 Subject: [PATCH] Feat/diff palette (#740) * chore(frontend): remove function 'colorBasedOnDiff' which appears to be not used * feat(frontend): add a function to create a linear color scale * support color palettes * put all together * don't allow percentages to go over 100% * highlight active palette * apply same colors to profilertable * fix tests and generate screenshots * address comments --- .../e2e-comparison-diff-flamegraph.snap.png | Bin 7885 -> 7846 bytes jest.config.js | 5 +- package.json | 5 + setupAfterEnv.ts | 1 + stories/DiffLegend.stories.tsx | 15 + webapp/__tests__/color.spec.js | 52 ---- .../FlameGraphComponent/DiffLegend.tsx | 41 ++- .../FlameGraphComponent/Flamegraph.spec.ts | 22 +- .../FlameGraphComponent/Flamegraph.ts | 6 +- .../Flamegraph_render.spec.tsx | 31 +- .../FlameGraphComponent/Flamegraph_render.ts | 26 +- .../FlameGraphComponent/Header.module.css | 7 + .../FlameGraph/FlameGraphComponent/Header.tsx | 47 ++- ...enders-a-double-diff-flamegraph-1-snap.png | Bin 25510 -> 25008 bytes ...a-highlighted-double-flamegraph-1-snap.png | Bin 26068 -> 25613 bytes .../FlameGraphComponent/color.spec.ts | 39 +++ .../FlameGraph/FlameGraphComponent/color.ts | 78 +++-- .../FlameGraphComponent/colorPalette.ts | 58 ++++ .../FlameGraphComponent/index.spec.tsx | 20 ++ .../FlameGraph/FlameGraphComponent/index.tsx | 23 +- .../FlameGraph/FlameGraphRenderer.jsx | 14 + .../javascript/components/ProfilerTable.jsx | 20 +- yarn.lock | 292 +++++++++++++++++- 23 files changed, 664 insertions(+), 138 deletions(-) create mode 100644 stories/DiffLegend.stories.tsx delete mode 100644 webapp/__tests__/color.spec.js create mode 100644 webapp/javascript/components/FlameGraph/FlameGraphComponent/color.spec.ts create mode 100644 webapp/javascript/components/FlameGraph/FlameGraphComponent/colorPalette.ts diff --git a/cypress/snapshots/e2e.ts/e2e-comparison-diff-flamegraph.snap.png b/cypress/snapshots/e2e.ts/e2e-comparison-diff-flamegraph.snap.png index 9511bd5e6d0743a96d8b2728c025ba8e9e6e55e9..9b8927bb71e714ba6d8ee7ecfca2f59efc2caf99 100644 GIT binary patch literal 7846 zcma)>1yGc4yT$WNs zK>VtMHTf<(=2TljW4}UIZx=p8D2cQO$;oxXC#2GNjKb8EjG-iXAsYYurl!r!C@|~l zY;v~D?7*%lwR>Z!O)loc=R#=@jnv*6MH-bxhQW`s5>$QWB*zMn|8~ zEiQi6Ef3$-Li|onk*BqGeCS+k*p=;nc5HDKARQ9{zTHoRu$Y7jX~!ymOoMVukdUksy$R^FF< zh%~ab)ipP()-d)vVOEI0V{USFNgXFYu@;ggVryr2SBx*2CnBVKW4tP1G=(bL=iK!? zKq6+=FNsMZVUU$KX-m_0=dS(UE*>_PwbbV{XXK z5@KXfY+TmeqhD;!gD~J%2gWPuZ$k@OovbGhH?XhcAXj&|P1kh;hU-NZS=Gxkk_+4#VUhvBAmxz)Sz)Er_pR!6KL4A0uE2k#AR3 zM#V<{Y9yzk3hzM89WX275fRKchY>>g_*~0ZS655YdMi@L*4mbj$m!^MwED$5u4xsJ z*g@w#Yi)^cGPl|+^o*C+m3cqn61@_AC(q|@xqXPo$F>eQcib8NS!j3M7tyx`pV=oV)Bw zdihWw^-n>7mKt*2LUqJS6_2^+y$>xZ;Vxok6wkg&6Ckc_kuudFo&4&&yuzCO-GrM2 zLe)Oi0YNE&rS8sZP~e0)Yf<3DscF{~N@B=q*r1M1s;By`dh^N(qvr=TFDuM&TEcHI z`u>s(C7HK-S|nXOhH|T^&K$AJ&(9AlT(yH9mho^{@siHXp{v4~8pA#^Ha1kF#R}fN zI5@}@^{2_1?e8tqVj^PMhwmEo!Rc4l$z5CdPHsw6^Z!@y8I^DNX|}aZ)%BH z8LebTB9VTFC(9P^5$+GK6G7fLybG#$OHrT(3k9l5YQNlf>?i(%jtF{dZT08=vIKmE zj5elwqoAyiKvm9?St#ZfIUaV2{+Ei1iYMC7*z`{>{{_4bL3|N4Nx>+Bo*RqxntJc()?KE@vjc^ z4l)aFZue6UFxp5hxPR@PrSqBNI)3xqi0-nO4+|rFL=$&|mM2s^J$-*;D8kaYvA1lo zJ1RQbY$1}=ufkVA?3N3aT9!M%-K5<< z@uQZJP7`;efh8f-<~)RNi#t$5ic{4Ox2#o-Ami6?2dseZgD1^Ae8BNw{^E|v0MNV? z4ufzt?UxRR4$aNY0~D!mO?c9)%L4-^>Ke_jhsnu#*BPy@uIar^3TZQ&L-1NBikV>V#|xXUOGVGMoZ=I(}d z9-T(~cb<;UV~eF1qXAQ?>O2JJ!}+xgs3{iU zr;nct=bzo@yg%3AyCsJhVswft+jUb?R=&+=h7Dj!1ATQoz-V`5FPpHQ0(grgl9vO& z_-*p%`2SY9t&e2>`sc(c+Fp zPt@KCwQIlFepinLm~fe*F9<-9(=_0}NAn3qyf&I0c#y^F^iFTP7w2Ua@iVHNET=wb z>~Bq`+V7lQ43CVtA9s?@%$9~+`5o%@u#nRvbhMnRW(Wdq178|Yy!JRqTppW;2hbc9 zI)V6P`?1}HsTw@S*0@3U^ynW-qeaI3C(#6%YOE*MiStg5Iv_II+Dhx5Uma)FT%M48 zfe@3o$1f^O*TPSZlhg&>_SqPlntmVnZ07KUbw=V9fug-1cCtRLur=KLe-f0JfYUuD zu`H?aarDH=kc){-h(UGd-7Qebe5~R6h$tdNIhE6OXI@Tz%AHuCuzls;R{ar}sQC&< zn-ycXj03vfn0HYBY?P3PzxfZGHoteGn~|#E`1}s2giTD?8LPTHV#u|$D84R^cIV^* zNY?-tdkk2H4SL^I1&DE0(dLXP&wl3Ega}ipMoss9-I&BDBFGy-nKu6{J^$eA1#N^0 zBp{g-Gy$a5xGz&b@)NB0J&<<)y=^K!RZk0ema06xdt;_N!aOVtROzYQT+m0YM;R&= zimHmHYlj#M%KkY>yg^yoh>*#2CQmBmvS=~>` zU{9nJ>$ibM5_)k8^*!1^jlbN(d8yR2luv(-FeQpiK^EG59s zGS`WhG?fVp^9BTXlgMhbKF`#bPHu>bn&Wb&62g&@4t1_;atfgmR(4JxRvpa6TnC;{|!;REfF5#UnT?%y{(9sXz&931Qo z1_u-^Blqrw>VBeBl{TaU*a>zJ*=^DwmPg`{xN(Pqu0?5-hcG_j%{DWBxT2B@T2uZG zU=?l6x5C2y=)jO#bYAYZBY44x&f69U0DI{xCpKRP~26<<`CPU!A78sc(qx{|b>c;4oAi zS*fOx(|B^s4|oecv~rvw`HCN`uYK#ty(Xs@CTFQl*_NMwZrer>e)G08@ZI2%jui8= zK0jlB`0(LVZ5?=NYO?90j3_)}R&mbw!7?7;)?ui&wtKA|LlCMMv=Waoi9L)9i69>O zVy}}2ho7wP^>;m1S4hf+{V*mZC}C!q-#ZiXU%Ju7Py6qQzmkz0W`vM|kFD+a)Z2(l zc*b6fAlmVNAR3U_Yfv?4v|?*ZC+e5x^t_hr&YfQCoIo{sAK@|0XGVQd^Jeot`zFKw zM@ZiLQN?{(GUm#Ue+|sF*nr+z6L8F{skyCc<|k@QL6v8F;N7WLmqvpi|1<(dBO&Ms zn{`V|-5#sE%`GRKKxzQq*xB17DIgMR8Q)HQ4g*f_gAD|BzE$h?oS<6vf>PgvKJasZ zN99*+5ey+g=|hNe7On))?|?Kv-{u|gXhach(m*4}QaKnqO}^Vec^r2wCYUO%)jb3D zNyT%B!IzzJLLSd5!ni7v;v$C66f^&7c)dBI`Db<*FrSlM}#z`%i$ zcO+Ol8bPiT5)7zhh^B9EyBInNOiG+aM$r4ftNQr%#`jY$xmB9bZ^jS|x%pTZwkIBWt6j_FG02a*RB8gMt1bRbbpfm1|>r`c9mX zgop(Q|J;Pwwe6ZARggAB7L7>W=SjAb$?G5)$6heEvL+ zM0)Cm*p&>31<(>g%kOCR#FHO1q@$lWee%eNU!4~h2ucW-`Vny*DAS7q)l4DZ6iEh2 zB{v?Fe1g0NMP_B?XM;va>SSF1vU#i6(EtcsF0K=~><-@tO=K<~muHa5xjt1%Sl%Vu zDDGda0mO-%nb~3HTe2%$9@*$@T-3I8gmxTrObXtC9YmLVJKPsTquZ@;4phz$n?6@l-Pz9_GroOj#VlRaW zv=0jt0u#TZ^^^jZYUH2%hDpA}{m7{fLaeB$2tXHR|It2ClU_8Z(%x)7U+#Ns1-2O=T^wO^QigbvJa7fxiy~} z#?AD zw5VaAqrgDIFkyza#lY$te*VPdjFJa#0O;j@_Yd?}1_N3$`o%b*d!v2%U=U;pwGl*e zT4q({j%S|1A;C5W-f7&P91^QDcY2GLdd>Gc-vFU?-<%Qx#z}3*e{LPYpb1x zJfzKG$*uNieNNYu(Wf4wt>JC5`V@ewqo$VT&u{)B%=!5s)T( zz)^nE*#mn7?kXU_do~vVB zofeEY>ym)62L0FQe_}~SPFB+1TH<-(!!tP82@!k^qF;02#-qtmeAQ?NiM5p zQ3Hz!whk@7bAeZ}5lB_hG=#|U#)=v5iKz7&YF|4jyJ#WSJ8mZYP#6ub%LGXisB-EW zNRyFKj~PgQ zf&3LDMa<4ExMt?&XooC8(VNOiY6jgMjiyXfVFBPXjR2xcxYAIhodSQ+l+BTPz4 zY7?!j>{>IuetK*UEi44A9mmHKo|s5hpq>@Y!p0WaVbw41zO=3u;HjUW< zNf~pdH{i3t&LY!#tzd?nP&GtS$-oov0I>J1vWN77ujGrzl1S+LKh@N{M-&XQKa2zT z!Y*gP;isV+3ABq%Oy`}J_5@pWFxIeORvpNh_m+EGC@9-He2?53$`ZTNRalC2{v=XG z3LlV>-HT@DX^%kZ)ZV@Y2pisHB8eD6PEGY>DnP)qFaEw|{F;PbJ>$9W;p>TV*4m@Z z#dOx31+T^{F)t!&NnIN@3GBZB))*Nnq_4d3k`JMl1EBD&TycH-x?Xwp7Xty{#fim^ z8IV+jI+`zpi-2POiOwc~$-iVF$pucY0@%Vo8Lft%wj4-r1NBRTO=ZGgi@7jJpGj`tt`j=GdozTlw3Q+9^J-y#AgrQ)c7mvj(?U{F=Q>R%3*qq~aFWCPn zegeFo$;Qb7QbV)}5=%-vUY!zxehtMYx+5NoZtQ>|bclnz*WR%wXUYhBmJpHI76Wv) z^l$l-*`o~5+<9NWQmM}EpejK0Y`ulZA+xXK@z^#2`V@~^P%K*b{DpbKObU1{SU z4wm7EkEScTi^Idi+yH){(_7Uc0Nr-m2lD~APKjCIt?@hj`dw-c(&}IG`G@OWeF@^t z%X{xYB)NAPe}{sKa&E^5eJ2eyBC43MoW4xOzc5Lx)%@|!=iY9Vi4-QxHi?xS0*UY5 zusTzq-`SQS1{VW97%jzld3k>#J3hr35G-(X* zh>n-%{om2t7#RqvLtRnc<|~@QUaPHls%F(PKseBsCDCtRQ$u|N7Z8CKi`s&cF%=b0 zKo2zw0-Ya%`+9}nplSW$_O2j&idotFGTj=SG(;M}f4Aa`|Ex)3UG4+X zkJFzdC;)>+HSIe%(Lx^P^lBmfK2RA=`=-)gH#_!r5O>peJ|3-%eWzDRN#8(_3zAcC&uX^Bj*w%v<1=(cZf z(*-*7x$8~45YJFO&DNl@{N>oXWL7y$&W7(=!>7m|UJ{j(zY zvL7G(`wk=xDfouit3hlGRJs`0n8}jrmovA2HNMgba+yHTL@rJy1`UbR|Lf|K9Rd`R zn0?o{Ft0G{uw$3DMy~Z^Tw!|TUtqmzu2RJbroj30B)%?b#gv#-3}h}?bCTBIulW&p zpTKT;HDl^BoFqpAdwbOZ^ku zVctIKdvWzw2NULBIQxEZ@+Wh9c?#&lE1p#g-`VB~bS9al?vGo+wZO~>QuJ%VdXIwx z2Vf?Be$9u@n^>@`Y6Z=umzZ*x_SM3FVOS)36^4i}8Z5yVm;sUT5!5GF-?p5@{Z3!S Rg7aq#ML9LuB59N0{{qOhJ$(QG literal 7885 zcmeI1cQ}^+|MwMTX2%sFnMGDt*@RHGWXldAd(Z4m!GeS*8{u~h<5e^Q{xx066-^0N< zRSo~vAvg;^-L`89aBvv^xqDmczQ?JJmUB9zXEK|&Hc3wA*>vQ(ms6e@pyC^@X;TS* zFXq2Poy9Q{Cdxva6w>vBk3)wEgFmAtpqy0Z|)>r|Jn!g2TR-O&#pn9n9Y ze@^+a?-IELT6c@t&U6BtV#`Qbdp(T^V~ z&z}z=UtpT*iOJ^Rr7s6h&SU z7CNH1_1{JJCGo~5CWf+eaYbRVYF=JmI!%7!mILWh*Uh`hwTg5Cl9FiMbF;Gp3Jb5o zuTn-66BA;)SQ({sp=Ypt2fY{!8#{Ywa4?>pzW!YW1=G=2>ZlmGL|&tTkHz}sdd2@F zB~_Ys5dHi*(Po+D+gb9U4%y6@n3#*gPIze;IV&qp_qDl}p!#2*yv2TuYT)7FVU0=~ ze$s7hY>53FH-iTp)>c=ic<|uC*YR@PxGotlFA;pwi0s;akep9@zI3^BW-ncL(KUBd;4}4g+)`=}UJKO4}-E?=kSrKE`1Pyp&u=q**ld}e{(e?T$*jjy?}oI!y+vuF zLi+oa&~9}Zy}b&ZG4x$CLQbCvhK7bXBc+XMYiq3(6cknzH8l(0ywR<5yQWeQ|KthI zWfqp#uU|8>vf@Q`w8A|f+1qo7h@{5Gl9m|Mwn8@`PxNcnUlK0Q&u4!gA74vfUS8hb z+38fbJeU=i-`JQ*uL;!+g=lHXA(9abC8VaSd)L6=;_Om!^{2~lH(}@Hxh;?JI(Obb zTd&jLbpxr^mX;QSdXHzjyDp!+)~~&P{~kH&rjw&hLSo`Y`0D!YUM|@B#F7%8ipt8K z!ND%;s(bqSif(Q(Q+(MDACa*hlhtX9$S~8@TQBGmo54&t{=G` z9k@>02||sucXjQw67!OyPScX1D-iG!NV%qT7 zSPM|B6&I0#OmRh69rR{FQV!?as;VI@_6dB{#KgoZl#FTM;K%yV=-Ale<|dSo>~*hQ zD-Z>%$B$*NyR4`odxy5DOo5s~pB&AeV7i~Ns8gT8NS^FSY8V;CbsF=LQ&6;24oXB} zEZQt8O{(;2)$iOPNa8h;BVeYs3sNaql!Ig6-2PU#c~4zk%Fj>YY)}AHVk22$Va~|v z3NI5A6SeI8WR;EWIfw2{m2+SUkM~lIla7q0$utl1L}3j&uMT7B;rNy0qo7!o|T6 z_Wr%dRW2@Q$%PclOcU5sFc!>8En!g0labYzrLbZVQBh(4W3kk=HEV7fVks#pE0VLg z&=K@iZ{PC4Ccgr7T6WkVY${u3n=O40(_3*SDqkw5l(vuW`7==Z+F z#;1m~qu;+qjBcjI3=iLHZEGVWB+M=5fKsb^5sj1!#zj4QK+>JQz@hr z7FG+gmS>MQW>IJ>aI`R1`P+UhCH+J`r*H+=RSl-Q{%EeAWn zRVOMfuRrXiURYezeP?^2X&+;c67%3|I`~jJUhB*u`Fmmz5e_4ttuv1wKQ^dyi+TGN z4OOjTVZmN4VA6_5L`>{hHv<}1%BGlzg+>J_1kFsB@J$^b*8%s`sc~Qi%Z5F>ugP}( zdc0K7*=*0%yrk})o|eU}xy{W%D3KxL@X$AJZbum%2Ck2lY8V*wL&c`>o1Jag-q`_u z$ZjHKl2DS8I)(Hr*db^$CQZ-`O*eG^{(WPClw=8Ckp?0nA|anWzOhoHg4)`Y(b4-* zF7VwKu3I>Kn-&K3RM$+XsS!fdx%hCeOLDoo>FAn-goK9}W4>})C~Rb<*AMIM?d|VB ze|9c8@%tb9pc@+-iwqm+!rB6IIN`cX?{C6T%E({!s)*pPrKP-f)oD;u&RnqRCc7&` z{TZUPl@tA{e%n-y2Wwnt(5-Y~=g>36G;ME#lKX~eWVmx9UNW#-x4Ha}rtcRaRxIQCD<92ey% zDJjeJig%srWk!pv0Jpzou&RqHqchG zaJ4jnV*&NSt2b}j<{cb>C#vn4QvFYU`FHj8MdixJRXm=$31;O`YhZ3}&S%Z203UYM3Jhhs&+N+ z-@mP`O)Kj5wRv&tX=dg?04{!bR1}M#U=j!r>=_se+m$O3>bY`T^I=Te;JQ0oT}&GK z`hD6)z8y<_N&8E@{yiDiR#wJG2S31Q|a_3G6eU}^?Y zHz0;Ps;Xa_1900rI<_8wtwJO5HXS~P%?~BH&|2}ZPmMYRj2Ad544`fAS%fs9ZjXLr5C|7FKs%E^2Il85tT_qDYC@U-+aVTc3>Bf`yg)z|GmiFHO_ zkSYB;xh%CuP}T1*ryX|rAL2tF*B>9OBRmg#dy!d01TiX`ZeXX$0uPB25)za$#ZthHV3vs*S!KO+=}C9@9q53){Xu_(q_?)Wkxn=~^nok- zW(WugO-AyStpNR2OFE2Jc@vAbn4tl7qdpx512;o9%Dd`z!iGZ<*apt7XtGHS7S#DJtRy`%za{cX4rX_%Fn^wY7Cy zP7ZvOORK2ax~jr%MkMqceJ2RTUUrSwkE<|>nLm7JB9Iau840!?q)$jjRseI)!@fic z1_os%B@z%_E7;Q2l@;T$k_T4x_4PFl^QU1r0K0gakPy;2HkJeik}K@GMh$n^!eU`fBW`rtPQMN2?|~ClSfd7sJm(PR0?<;kQ!59bMq}I3{a$? zmRqv2XW(!8ghWK9@PTw8$3VF4@<2x4d)IXWGP16&uCOFSFG83vVgLjEVLiyYasgF$ z?`fU~J6ieS<>e{Hc+lI^lU-603nW@mQGv{6$->U;(ga(+!y~G&EU15{<3mq0V7d-B zO<-UkO56(#qX&#*XeR$desHqgu>XZ#oY$_giHW7dp7i$ihDSt5nf(RFhI|fI3&8dT zT-WXc#L?N?+rO`?8>&A!{{3~fDQk1&8H;>(Utew$O!kl|1c!xDQBq3l>R#aI=bu)1 z{PSr4_ARxtySpI$P1`x32rHmnA(s{MRM3Or;bAK) zt4rM6(E|f216h)B`S0J;MRiE4sgciin3iKdew2g5PGymg#je9tfanC21~e)l$o$^c z;`FQR>{C%4fqxF!Z~MoOhaUq2=(%$f_%FJ75zQijs!cFgl0R_EUYz zUx7(%Z!V}vw=#65&K-(~fRxl?`*V*K%{9H-Dk`LK>*ggV3MMAiTeomhL5TpiWZDb ztW#4{Bbbp>Q-dcii31nqzkC@C^!+UXdgPvl225Ix_As%PKkTD{8J9vjye|9y2`-(D zXIIVv>OWD1G3Mn<*0r@Ya$H4UU-3!{OpfH_eTa;cB4DjC(Z^;@&^i08oKv0Q}71YO7`1NWqePt#kc8NKCKVSKBun}KO!R-lL}`3EiD@8UkIK>L_}&5zJGV1qodP- zc^)#3_V#x2ix;Ew;k+PLblaE=>4doi`ViSVfCoToD{!xgde7^r8U-rz{~1%U2??Pv z$^2$mz#kAMEc(U`Bng_Zm7_X;z5^yLETB0!tOrc+#HmeiR9k51{F46QJUe55Ri^ zNUw}RY>9v>>T#F}pN9{UQkU ztD+)S2;eOBpvL0etteUI9LtFPT*C#G)(7|eUmbrG-F&?JclYJ14GO*a712t`7@AN zQ$7?HifUwLCT98Q*R18q@sUqf>_uT@jy-xhM3By7kJWEWJlaayw8}9A#K*9|nA-rJ0!rOpgL+uiS zd5qv}yLHubNS_rHh#-#tB6sfGIjD2Qr>{)k($wU6@V*^J#Tv-l`Vz0n?10IC$I6hE zTMb=4jf{f8(Mo=3xb30 z?r!6u99aav!~l|@9@(MDVCE|`ZaH1w&;WxSL~jncWRizZzhruoG6&aaATRC`yuU&~ zZ~nRaS%2z{DDNfY9g;!K)0~{k)Us03^i00H6s1kaBL8-2Gk<+^_}_A-Z^NuF;!liJE)l+3v|mNStYgy0c$7F?vj=oSGrkOG;O-0F zW%#dfCIdp6JsP*`m3#xp#X zc$#;o_)W8yF&E!i&Sm=SW-a&^8Q-a<7yhw0Lr+?b-rz=ii4!4@_{*4bHXLUXhr<}J zzgeM~zJ^4s->44fGfo-=Cj}SycB=h|(tmkik%#ahtKUl`#h!|37BLnsBlURRw2bG6 z%Z(q3^}qUJ(Ow+aW8LM?i_}JZ`Tb79ODF=oX;Ce0YZ>1O*U_l;SryGYPm z)oZ76KN0_VLY~*nY{nNH2z5FI8BZ~ura2YRY2c0==yM>_EM_J{)Bo>GEo7PFJhbW zfR?2X83az()e8UZ1ut@@j%h#X@#jZ!w`E+0$Kp;-N%s3(qkC|N7+zE3+?7?iT_SB9 F_&-AYNFV?J diff --git a/jest.config.js b/jest.config.js index d921701118..b863f4d233 100644 --- a/jest.config.js +++ b/jest.config.js @@ -30,8 +30,9 @@ const project = { '\\.svg$': 'svg-jest', }, transformIgnorePatterns: [ - // force us to transpile these dependenciesmyth - 'node_modules/(?!(true-myth|react-notifications-component)/)', + // force us to not transpile these dependencies + // https://stackoverflow.com/a/69150188 + 'node_modules/(?!(true-myth|d3|d3-array|internmap|d3-scale|react-notifications-component))', ], globals: { 'ts-jest': { diff --git a/package.json b/package.json index 89df9f5ed1..ce75529b5a 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "@testing-library/react": "^12.1.1", "@testing-library/user-event": "^13.2.1", "@types/color": "^3.0.2", + "@types/d3-scale": "^4.0.2", "@types/jest": "^27.0.2", "@types/jest-image-snapshot": "^4.3.1", "@types/lodash": "^4.14.176", @@ -157,6 +158,10 @@ "color": "^3.1.3", "copy-webpack-plugin": "^6.3.2", "css-loader": "^4.0.0", + "d3": "^7.3.0", + "d3-array": "^3.1.1", + "d3-scale": "^4.0.2", + "d3-time": "^3.0.0", "date-fns": "^2.27.0", "esbuild-loader": "^2.18.0", "eslint-import-resolver-webpack": "^0.13.2", diff --git a/setupAfterEnv.ts b/setupAfterEnv.ts index fa28d395b2..ed48abcb81 100644 --- a/setupAfterEnv.ts +++ b/setupAfterEnv.ts @@ -4,6 +4,7 @@ import timezoneMock from 'timezone-mock'; import { configureToMatchImageSnapshot } from 'jest-image-snapshot'; import type { MatchImageSnapshotOptions } from 'jest-image-snapshot'; import nodeFetch from 'node-fetch'; +import 'regenerator-runtime/runtime'; expect.extend({ toMatchImageSnapshot(received: string, options: MatchImageSnapshotOptions) { diff --git a/stories/DiffLegend.stories.tsx b/stories/DiffLegend.stories.tsx new file mode 100644 index 0000000000..63f9bb41de --- /dev/null +++ b/stories/DiffLegend.stories.tsx @@ -0,0 +1,15 @@ +/* eslint-disable react/jsx-props-no-spreading */ +import React from 'react'; +import { ComponentMeta } from '@storybook/react'; +import { + DefaultPalette, + ColorBlindPalette, +} from '../webapp/javascript/components/FlameGraph/FlameGraphComponent/colorPalette'; +import DiffLegend from '../webapp/javascript/components/FlameGraph/FlameGraphComponent/DiffLegend'; + +export default { + title: 'DiffLegend', +} as ComponentMeta; + +export const Default = () => ; +export const ColorBlind = () => ; diff --git a/webapp/__tests__/color.spec.js b/webapp/__tests__/color.spec.js deleted file mode 100644 index d15147317c..0000000000 --- a/webapp/__tests__/color.spec.js +++ /dev/null @@ -1,52 +0,0 @@ -import { - colorBasedOnDiff, - colorBasedOnDiffPercent, - colorFromPercentage, -} from '../javascript/components/FlameGraph/FlameGraphComponent/color'; - -describe.each([ - [-300, 100, 'rgba(0, 200, 0, 0.8)'], - [-200, 100, 'rgba(0, 200, 0, 0.8)'], - [-100, 100, 'rgba(0, 200, 0, 0.8)'], - [-50, 100, 'rgba(59, 200, 59, 0.8)'], - [0, 100, 'rgba(200, 200, 200, 0.8)'], - [50, 100, 'rgba(200, 59, 59, 0.8)'], - [100, 100, 'rgba(200, 0, 0, 0.8)'], - [200, 100, 'rgba(200, 0, 0, 0.8)'], - [300, 100, 'rgba(200, 0, 0, 0.8)'], -])('.colorBasedOnDiff(%i, %i)', (a, b, expected) => { - it(`returns ${expected}`, () => { - expect(colorBasedOnDiff(a, b, 0.8).toString()).toBe(expected); - }); -}); - -describe.each([ - [100, 'rgba(200, 0, 0, 0.8)', 'full red'], - [200, 'rgba(200, 0, 0, 0.8)', 'full red capped'], - [50, 'rgba(200, 90, 90, 0.8)', 'half-way red'], - - [-100, 'rgba(0, 200, 0, 0.8)', 'full red'], - [-200, 'rgba(0, 200, 0, 0.8)', 'full red capped'], - [-50, 'rgba(90, 200, 90, 0.8)', 'half-way red'], - - [0, 'rgba(200, 200, 200, 0.8)', 'grey'], -])('.colorFromPercentage(%i)', (a, expected, description) => { - it(`returns ${expected} ${description})`, () => { - expect(colorFromPercentage(a, 0.8).toString()).toBe(expected); - }); -}); - -describe.each([ - // red (diff > 0) - [30, 60, 'rgba(200, 0, 0, 0.8)'], - - // green (diff < 0%) - [60, 30, 'rgba(90, 200, 90, 0.8)'], - - // grey (diff == 0) - [0, 0, 'rgba(200, 200, 200, 0.8)'], -])('.colorBasedOnDiffPercent(%i, %i)', (a, b, expected) => { - it(`returns ${expected}`, () => { - expect(colorBasedOnDiffPercent(a, b, 0.8).toString()).toBe(expected); - }); -}); diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/DiffLegend.tsx b/webapp/javascript/components/FlameGraph/FlameGraphComponent/DiffLegend.tsx index d4cc1433d6..7c49e841b2 100644 --- a/webapp/javascript/components/FlameGraph/FlameGraphComponent/DiffLegend.tsx +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/DiffLegend.tsx @@ -1,33 +1,40 @@ import React from 'react'; import useResizeObserver from '@react-hook/resize-observer'; -import { colorFromPercentage } from './color'; +import { NewDiffColor } from './color'; +import { FlamegraphPalette } from './colorPalette'; import styles from './DiffLegend.module.css'; -export default function DiffLegend() { +// TODO +interface DiffLegendProps { + palette: FlamegraphPalette; +} + +export default function DiffLegend(props: DiffLegendProps) { + const { palette } = props; const legendRef = React.useRef(); const showMode = useSizeMode(legendRef); const values = decideLegend(showMode); + const color = NewDiffColor(palette); + return (
-
- {values.map((v) => ( -
- {v > 0 ? '+' : ''} - {v}% -
- ))} -
+ {values.map((v) => ( +
+ {v > 0 ? '+' : ''} + {v}% +
+ ))}
); } diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph.spec.ts b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph.spec.ts index 60311a204a..94af55b6db 100644 --- a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph.spec.ts +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph.spec.ts @@ -1,6 +1,7 @@ import { Maybe, throwUnwrapErr } from '@utils/fp'; import Flamegraph from './Flamegraph'; import { BAR_HEIGHT } from './constants'; +import { DefaultPalette } from './colorPalette'; import TestData from './testData'; jest.mock('./Flamegraph_render'); @@ -31,7 +32,8 @@ describe('Flamegraph', () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -76,7 +78,8 @@ describe('Flamegraph', () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -166,7 +169,8 @@ describe('Flamegraph', () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -246,7 +250,8 @@ describe('Flamegraph', () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -312,7 +317,8 @@ describe('Flamegraph', () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -391,7 +397,8 @@ describe('Flamegraph', () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -473,7 +480,8 @@ describe('Flamegraph', () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph.ts b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph.ts index 806ba6efbd..aade2977f4 100644 --- a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph.ts +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph.ts @@ -3,6 +3,7 @@ import { Flamebearer } from '@models/flamebearer'; import { DeepReadonly } from 'ts-essentials'; import { Maybe } from '@utils/fp'; import { PX_PER_LEVEL, BAR_HEIGHT, COLLAPSE_THRESHOLD } from './constants'; +import type { FlamegraphPalette } from './colorPalette'; // there's a dependency cycle here but it should be fine /* eslint-disable-next-line import/no-cycle */ import RenderCanvas from './Flamegraph_render'; @@ -38,7 +39,9 @@ export default class Flamegraph { * otherwise it will be greyish. */ private readonly highlightQuery: string, - private zoom: Maybe> + private zoom: Maybe>, + + private palette: FlamegraphPalette ) { // TODO // these were only added because storybook is not setting @@ -82,6 +85,7 @@ export default class Flamegraph { focusedNode: this.focusedNode, pxPerTick: this.pxPerTick(), tickToX: this.tickToX, + palette: this.palette, }; const { format: viewType } = this.flamebearer; diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph_render.spec.tsx b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph_render.spec.tsx index 9bc4188246..8bfba8dffd 100644 --- a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph_render.spec.tsx +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph_render.spec.tsx @@ -3,6 +3,7 @@ import { createCanvas } from 'canvas'; import { Maybe } from '@utils/fp'; import TestData from './testData'; import Flamegraph from './Flamegraph'; +import { DefaultPalette } from './colorPalette'; type focusedNodeType = ConstructorParameters[2]; type zoomType = ConstructorParameters[5]; @@ -23,7 +24,8 @@ describe("render group:snapshot'", () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -38,7 +40,8 @@ describe("render group:snapshot'", () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -52,7 +55,8 @@ describe("render group:snapshot'", () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -69,7 +73,8 @@ describe("render group:snapshot'", () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -86,7 +91,8 @@ describe("render group:snapshot'", () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -103,7 +109,8 @@ describe("render group:snapshot'", () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -123,7 +130,8 @@ describe("render group:snapshot'", () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -141,7 +149,8 @@ describe("render group:snapshot'", () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -158,7 +167,8 @@ describe("render group:snapshot'", () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); @@ -175,7 +185,8 @@ describe("render group:snapshot'", () => { focusedNode, fitMode, highlightQuery, - zoom + zoom, + DefaultPalette ); flame.render(); diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph_render.ts b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph_render.ts index 0952200aa8..0851185e6e 100644 --- a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph_render.ts +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Flamegraph_render.ts @@ -45,6 +45,7 @@ import { getPackageNameFromStackTrace, highlightColor, } from './color'; +import type { FlamegraphPalette } from './colorPalette'; // there's a dependency cycle here but it should be fine /* eslint-disable-next-line import/no-cycle */ import Flamegraph from './Flamegraph'; @@ -70,15 +71,15 @@ type CanvasRendererConfig = Flamebearer & { tickToX: (i: number) => number; pxPerTick: number; + + palette: FlamegraphPalette; }; export default function RenderCanvas(props: CanvasRendererConfig) { - const { canvas } = props; + const { canvas, fitMode, units, tickToX, levels, palette } = props; const { numTicks, sampleRate, pxPerTick } = props; - const { fitMode } = props; - const { units } = props; const { rangeMin, rangeMax } = props; - const { tickToX } = props; + const { focusedNode, zoom } = props; const graphWidth = getCanvasWidth(canvas); // TODO: why is this needed? otherwise height is all messed up @@ -91,9 +92,6 @@ export default function RenderCanvas(props: CanvasRendererConfig) { const { format } = props; const ff = createFF(format); - const { levels } = props; - const { focusedNode, zoom } = props; - // const pxPerTick = graphWidth / numTicks / (rangeMax - rangeMin); const ctx = canvas.getContext('2d'); const selectedLevel = zoom.mapOrElse( @@ -243,6 +241,7 @@ export default function RenderCanvas(props: CanvasRendererConfig) { spyName, leftTicks, rightTicks, + palette, }); ctx.beginPath(); @@ -336,6 +335,7 @@ type getColorCfg = { isHighlighted: boolean; names: string[]; spyName: string; + palette: FlamegraphPalette; } & addTicks; function getColor(cfg: getColorCfg) { @@ -370,16 +370,20 @@ function getColor(cfg: getColorCfg) { const leftPercent = ratioToPercent(leftRatio); const rightPercent = ratioToPercent(rightRatio); - return colorBasedOnDiffPercent(leftPercent, rightPercent, a); + return colorBasedOnDiffPercent( + cfg.palette, + leftPercent, + rightPercent + ).alpha(a); } return colorBasedOnPackageName( + cfg.palette, getPackageNameFromStackTrace( cfg.spyName, cfg.names[cfg.level[cfg.j + ff.jName]] - ), - a - ); + ) + ).alpha(a); } function nodeIsInQuery( diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Header.module.css b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Header.module.css index f3db1ccf96..7ebf9d01df 100644 --- a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Header.module.css +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Header.module.css @@ -2,6 +2,8 @@ padding-bottom: 5px; display: flex; justify-content: space-between; + + align-items: start; } .flamegraph-header > div:first-child { @@ -18,3 +20,8 @@ display: block; text-align: center; } + +.buttons { + display: flex; + flex-shrink: 0; +} diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Header.tsx b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Header.tsx index 0360d17580..11fe3adea7 100644 --- a/webapp/javascript/components/FlameGraph/FlameGraphComponent/Header.tsx +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/Header.tsx @@ -1,15 +1,24 @@ import React from 'react'; import { Flamebearer } from '@models/flamebearer'; +import Dropdown, { MenuItem, SubMenu } from '@ui/Dropdown'; import DiffLegend from './DiffLegend'; import styles from './Header.module.css'; +import { + FlamegraphPalette, + DefaultPalette, + ColorBlindPalette, +} from './colorPalette'; interface HeaderProps { format: Flamebearer['format']; units: Flamebearer['units']; + + palette: FlamegraphPalette; + setPalette: (p: FlamegraphPalette) => void; ExportData: () => React.ReactElement; } export default function Header(props: HeaderProps) { - const { format, units, ExportData } = props; + const { format, units, ExportData, palette, setPalette } = props; const unitsToFlamegraphTitle = { objects: 'amount of objects in RAM per function', @@ -37,12 +46,12 @@ export default function Header(props: HeaderProps) { case 'double': { return ( -
+ <>
Base graph: left - Comparison graph: right
- -
+ + ); } @@ -53,10 +62,38 @@ export default function Header(props: HeaderProps) { const title = getTitle(); + const paletteComp = + format === 'double' ? ( + + ) : null; + return (
{title}
- +
+ {paletteComp} + +
); } + +function PaletteDropdown({ + palette, + setPalette, +}: Pick) { + const palettes = [DefaultPalette, ColorBlindPalette]; + return ( + setPalette(e.value)}> + {palettes.map((p) => ( + + {p.name} + + ))} + + ); +} diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-double-diff-flamegraph-1-snap.png b/webapp/javascript/components/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-double-diff-flamegraph-1-snap.png index ef7f4e72ea04b710bbf0d281760f8d71231d2d4b..2178c3a9a5cff8542c07702d6af237751f2d3c26 100644 GIT binary patch literal 25008 zcmbrm1yt4Bx;Kp5KuHA=q$Q=hOGUc7ySqCD0cq(5=?3WrY3XLs4U4Wt=R4W%bME=> zd+!+U7@ylQ_TI8s{MVe%e4bxT1EnQ}kP)yE;NakpMT9@g!ofWzgoAtZ{P{ERC%G@b zV}pM^(-jl?40r$V&yS|uC^$GmIFZjE<(-pv=Uv?8*PAYmhNu&0nBMjE>l43tVfOq< z+neWHKHrFle11$W%$%vtYRXVipw%Y1o)muVT7HmBTWNJk2w)`F;3M zK9doF;Vtk+-nhu+s&qv>&^v^6+lM&yAM za0%l6BgQ0>xeb)9sO%}x3i8$mXM35kbaa%uE;6r5_vV8SGTyOWFS-O^h{f5?($q+6 zs`S9z7K4?r2Bld41EAQ69OUieFw)4mWkZk!0SoL;GehExf8QSP0)E z8mt-#DVbo%#Fnj2nKJ$6sWEe+j0taAI1CT3!<4zByIZTgcz*duO-)?o__#KYPuULI z2M;~sdn3`#H7tB25TsZmiq5=k_LroV%A|fKn#fq#&T0@C3RK%7}1zBG= zV&61s((Uc-nJc%XPEaYT+Z;Nao?;CL{A6=hoFrDuEbG?4 z;IOfATsAJDBc@eTdyWX0wED2Un#W70uG5#tee#M*QSsls)oGzSTDO#CWo7Sn(0&bS zH2jWdk3b22nlvwYSEMq>HrK=Lx$@+p0yIm>6*F52o`1%GKIMoald)h7{HH0jAu|>{ zj*Lz01>4!-=5;kj%AbGZ$yd5N-5$%euYHsukbJPY1P$jA{OIX9wdXCXFBd4!yh_x zn>Vh%Icqw7Gta|Qq}qHFw1O&7tjM%^v~=VOYSE@)z7`(7j0;x=I0G(a{H?;ogm@C8AE=jaE_fV{A!?Jwt2qjVhnMcru`!SMt$0(twn$kQ zT&aRFX*<>(VHH|;kuFc4>Psg7PHzt=b96XbCAfPTBP*ij#`Rc|+_Z{QUqcj&H;pqT zjLz#Q7<4n(@67OW&;uShdo1$e-}EZQvl<|D2LCA~DDXV2I56nIV?t7ngz@Ot*hz^Q3(d{xj|wM5L)63OEn6DD2_3pNWs;={tsFUj z7tMBV)I@1K$H#kvXj|vLX~-v@C|PJQpU9FIEgFW))iq8bSL<-=YFl1WT8pH|uz8x5 zlXZB!KMxN0PuO~#Ouqc;)hMKAEVrk>|8rXOYjswKWBvMu2AA`tkD`6O@jPaV@^FHLWR0tbE^cu@3}l|0r2`lJD@P{C~+Z141U+I_)6K6nF_A=(wT{-fNNzZ>g0&zCi8D?ZOseM{HJF*2zZ?DJ2pg!X8#uI z|0qov^D5x*$zP8g_Z9}G?ZARbl7U|rpYKJtDpjwpuQN5Z3MZcNwO@s!a>F4F5C@KJ zwdKSpDavZfw9c@Y{j_&1-lFHg5EA<9MJIB z*S5wQ4@bp{G|POd%qExY>%d01TW=2MohndH4D+T8F0}{+<r^PSRgY+4p}c42-!Vw3#*P1?lq#nBnjfX=qYIy>LKdN)^4 zj9Db)@GvQH;a^}hmpx_#uWn7|0ISZQJJBoUb!TU(+Jv2{87@z`-U^TZf#W8Y7@Y7S zgYpq!IXfmh7|hqjrEwu|dsG<>9o^>SY{j-tI$vIylS}Bf1wVZS_cAs&yXrKtfA-a% zE}cQ#;Bb3&U+b*nrA0tM!0|~|7L7G2wBzd&U0q$U?Y74!Cd{TR0Vo7r8`jp)y&8C{ z!>$=xIQNSYp-p>E+@>a6=K~(lZ{E5>- z6OxiltgLcNOT)Wz$YL=t9`Q$w-or3k2&c6PnTUxCd2d3@ zu>lRomK~oTYp3(PH3K_Io6vo9mv%3%`{^%4{{Z$!c`VprY3v`()NmMVImm~S)3Yk0 zxhxxyEzHfQ*tMprf~(IQx$#ju$)!M7P;R!T5Y2uVs3-&+KC<~8b94P>R*fHBRk2?j z9g&cdmbo2hYHwOR9D@(#tuJ>kz7~iPc-%199m9O_>QGVebVYRDJ!?vxspkX;=X;NS z<9#ll&fc~z_>_6_1>bEnL8G0nup&@9XoLkp310ju;<)up1}?&9zK_nA2%){bdHJPA zcXM^W^%=onE1TW}E$2sQ=z23AmvlImF4Lr=X;or>2$JYvYIb&23^;r%r>;FIyeU)5 zI9i~wn%XjwOQy8RD+z&-A#cY;g7yOK$BaJqseD6Dbu231)$_EWfW?E{lJqZNl!iQe z992F88IE3(|D5a2f|-R=;X?p@}F0J*T~6I*clGx zR8_?s_lo}Y1n9$R>fy*D@%J{{WXHX6#FB|G!Eaz1EZb{0httnKj3`1;9B@^`2Jb*prQ{7D+7JK z&Z-+lw~OK3ttpr54ZCe!vL6h(_!H~v;o0tNcdtPo08wn5umAr3uPtIHC_J9FjPd8hJ^5HGoAH?FAIRV4K+H+_4^bdgXFCS3{T+((>0jU6@>q6D zYmH+phm?7I+&*6Vo2s4D z#;mJH&LytRZP29roM)vFoQZmXxGrw*%y1+Ao+WMT4JCNrOZF`}sbjxyftkCtz26-6 zN+Z?ml@XZN4d?p;v~l683y?)A-)V6xtwm4?VuN$Y>5$j+@5O3*+7*V}_e-x2L!x@A8t`rZJ1783tPGH*{Z znX@wq9)&Qj2b5liM4^&ajI9D>Tv}E&s8jcy)kePz^v<>ybgS-GR6e9T{KIPiWsg&= zJP=b9#li==(7i4m)5akthzl;a`I*;VZWPMK4*4ojDIPW~-lt}?waGY${Jmex6-4^* zS>OnrjLToaKik~i7tEHAOo;gS2R`R1P{NsRZ~yN7{UKfY$=I`J&#ddzv$AuDB806u zQgS0e}ho&r8?mY%F4YVcIf0N1L}TjBfq`o0^}XH@xp`?U`il__*tbKnl2E!tV? z2}>%Re53+a@Hm4=bG89<@mu=GW!)D_&pc$&Q29=z56?ko05k0OVDDer_g@~b=^It( z?I?my1MTh04Es0V$Q-2kTw>%H;JdJ(IVvj`Aui>j`(+FsMEdUBBX0PLA%N#;iP^8I@XqniN2x! zPdf;0v-6@yD^9afs#}d9M z5I|#{#Vr*RJv=w+1KG)LYDz)gfmFD5B6xqd`RiRDekkZe;Attd86VhppgOJ5=%G#O zzqrZUI(2+T3tLIahxKQoV2H@<>;wdDNun6^t>&_b#<{t?UIzS!b@va(qoFk%@p&pt zg2t^$mn$ZE(G%|Z+0Kj#)ItU9IHNbWydcQPX}`mmUb|v?s?vto5AhA$*J2~h(zq15 z7I6aymcSP;ey`g$-%XUF;oyk6iJz-_ zNd9SE?qq&=KG`G27e}aG?Aw8sB>y*X7ZH-`%y9T#!~<;)V~3UVAOI$3PV8noy^W)9+G~X zoD$c)5sKrx;{XW4CY@JLWZNge6Q|huV>HsGKXV%bkOw|tW^De1=`$XDut;FuTh`!! zi3-XOP}g^3Z7<@WDM_ql_rD&2iH~Dd=jUP7Bmg9k!dSX+to!xnm|~Rx9#c@!LBp2q z3~Ocq1m2yiGTTJ<8F=F$bojeWZ?4=DkF8kMZwQ)MS%ie;3VT(OipS}WWu}D5cejix zLlIM1Rl~GopP^XjVlaeXJ!bJ7+XdZ6fnUM$z&%<0_8KaD9FO%39{%5~4ffsZxEw`kp7vfM3z&A(r`v_^ zUn3xF^e>;OS%nthuG-WYU~L)OFi^$PBHxvShCU_qa-NC-v{KiV6X+b`VZ#wKwK|Uh z8A;~$NW|214Fs~sPsf48Z>Q$Jws0#3>*g)Nz8=4VsYHvC(#BC;Tq~a%4DShY=+=Eo z$2xsUD4$GxdVY?MiHTX=_-AUe_13odWXn_9aHRYi9*DEMSR4W4;KIH6Xx~;`un9k3 zzSkF(+uQbH%Z~6R*69-uYwPd+U4oz+kA%jHDm{@Li6COH;%EPTYL%OYln| zrKpgGiP-lR9!0%ey;u=GV13G*)v@J{6L6VVV}$n8{1&-mroMJO3+~qz%|}bVU^!v1 zZhXB}e`L_3fP%qNRRv}eTGxoo^L5)kxZ(dGKPxLM!^X@fXQxjCI8IMb1tuc!adES> z2XVntrjMDf=knciuoY|Km8Fv6go0Vg#Ky-LAJ@G@`hW4e@6qvCtYIA;p8+?iRi~Aw z!~k-p4Bj*#ipjqgMrT|lHunC2FLmVAeQz)`4nZ|s+;~c+a4>DZup;Ss_V|GanW(%K z^&`5#pa!}jP!Hq!1nk86hU*3OrW)-z@qp^Kns1b5&^ek7#)ROpj@txmVLdo-HvUY^UZmSQTJpq zH5Fx0fjQt)vCBH*fEJrZQ8@S0)*#WJoaqhjPG>Ig0t^9K=kNU{Hy3bcbWGw;tAXw=D47_iud&BK=$YPwaBk`w1gaJKXtl%>E6jMNnf^uiJ1LS zyYGJQH=HjZSMTq)1)~EM^$#!6p~2KQG8mbg5!LYE0ZNB;y?Xy(AAhmz2w+$zCSyKn zI2PdG=RCqfdN$|ln@mNOnbVwlX$K{W>Y0Ld;lyumgNjjZsLwMqCZu3^6)Fg@JUKa6 z(#D1%;7CWVO`vjf*4F6FHpD@1H&}lt*U1u19@D{x!CX}w3Wn)Y6twy7?z_uiGK24b zr%%4!@8pvK&)1!92MALb>*^EaH#tNlAt9N9BHi&qxmc@)*16&>Esgwi<}`}7tl}Gt zm>A}oN^8i*Kx+-E12Xc1F66N@nMVeBJU%{oyevep47)tMzRe7qUXOkE^11a*#|zN; zBAiEX{PN{;h9QeX)1$HgF`Zj1;!n&bHqNPI4;TXFXt<-R+@ddbDJjbO)clh=E>J&z z^y+5-sOe${eFn8!Ti?*Fn58Jp`+$Sf=fUOpWQV`@iqUP78n^~|g{4MYk)(iaBWw%` zq)UGdMPE8eU;@TMEVb(EiOWAiKSVrq!2qJKKaCc76=~J{KbE$Pr2liGh+aPDCi)LTgZaRQjy&{~{vk9^mJ$9}p7L97 z?YQO1Utdyj@cwO%c&%oQw*2a1t_Quhk-`p)pl4~o{zYbLaw z$84N${;oA%7ORnrhHM4~r%+{Pex%la%!nt;^{?<={$Y3@UzXsEJo-oe_-|iGG8=tl zVr-eSxYbDMGQrBaV%tzEs+k5q;otzg7MolR%hYscW;Vc>x|&K`1ZXxClOHSP@+R#h zSvTByZo{A|dUEKGA3s(iEd|V2ofe|dvs2Lp^dJjHpzn^1kJ@Io2de7HMH#PtwE-+c z@V2J1q!|cQUcfi`I#ddNJcsM{YYiSHXkYVC(-}6N;tqHVLF^Ofyn^D+g;^ZOrhAt= z7uW0S?i9y5m$2;98yC&_7J@o;UQ-t>FTRaQ#bmuXVbC}_=SDv%SXdn97H1L{R9YtO z)lUY>bq@`XSu{|(>`h-jQxto6I>9aD8fhgBzU|yu*L8@SR9xs_*wA2=CjcNN`}>8F z5X1&YovmH49P`4GalttohR+1KwU3>-ak=fkHC>;>y6$e-=<7GDs%k3S4i>~_YCjNu zFmt;mh0Z^COZpDV)T=Xbf9xd&!P!N?66Ne*qHTDPx7ZDAW4(Q1;E% zqyT-yh+7qOJ>JUQ3O=^l%8x_?y8eT?wG0yjRPd<53ASMtu?JOEQNZwWU&pXit&eW7 zY&sPTK%Z;~Kq)K8dmi}tFQi);&(q=>b`{ki-gl40lrYZ$>OzF}102&+Xw~G`y(55w zgZL|?CrU(25+zAdUAC?Hd{Kxjsx0H@cZa?>t<22Be6IZk=YjJhm*XRNA>$&ZD1C7R z+9W0~*1)T;RK4fBJ+ioGnym94voZe83cFMF;1LcJYTpI^|Sg+!!V@zt*whoNw*R<-t{T+7T@=Eg4 z*XB5=-ypg$8I`Y=G<-7P398EvB)_{5BHOfAZfKaUc3~1jKz#A!ug0@3oMcLhcYrKN z7RKzURsYmp;Qlw~?R#Ks5`~HyF^mC}{I$xoHSQ0d7`OfVTFqYv-STREPWYZ!DT;0i zy)cy;(@R^=^KrS?7;nM~jC=@@>arfMZ0==yX~X4q(1RxPF=LHfOg9ppoI~Ony83GSCO0L(Y8)B%LeOb$&$SVg_muy zG_3}_Eou6`U$orsufZG~jE*_FN#*HJVhM)(DjwCN|LVNPWS-M-DE^hhOm}Ce`+eHo zi)`5*x>R>YUHGh_k?vpK==t(Nw31?ka7|&FNIkA_GpaK-XIv3I2Ajwt#;d%yt5fq6 z{6mLPx0NCC;mCo0+9G;cMgiS))?tP)F2JgDu@pZBKNo67zcTO}uDxaSA&{Bj4G`Pd_po>{*}W zf@q;>)vms!l!_Y@Fq6ZX*WfuhM+PSs^~2ftuJ+sZPLmQVB94jo0(T~AYhce>S_pt* zkt`_$_j7hH3(3hkNln#%hM^8Ovz5LcZ)ZEB&}@@N0gz%qFSS+wyTJ!>;aeQ}qE0K6 z7R_v0_m9L-R@M`N9!NKONlsqeALK+(67}>Y1gP>K8%E@gJVErg;zyV^V zp`c)g^20__Qr4dDHwe)zdM&{Li>&P5a)Pf301OXm4p3shSmCytp0!-l0))L@eY!(Y zTC{cX1AeIov^EI{kcr7$TP5CS~U2=2egQ)UCj7gN(S0T7T2z-8|CxE4R=%N`Xj z-klXVeE1XtB>aF7Qdu1Q0(YP<;NQ(ae0CJ%6-MUA_<`LhUlyhSPgk1=LHOL9wUehXo^<%G`BsL^3gGq8s(oHxcw;{cHkp`p%U0DF>F?M>P4@|lv1Tsr|^eZXNDSk{JJol?`jhx1RRk5N#9h0=LO zEONt;@D!E%knw$-eja?yPGK&ZTLZ30w@8V!;vLni+$62QZ)6V%D{P9sTM z7c0ml^@mqmS=fb(RPk78(30A})MfkW`|6DI@@JEhk{m*!$VZHsJ5bmzz>MLnNKhHe z)l$Wm;~{9geTR_k14c@bBEOIuxzl`2!rO`*n|*r@3!1%)MorEcnj+1X$P9(xFX=e5 zk?7f#%+=NhO4Up*u9EbN5Un{ORYA%WJVjhb___)sYbZ}r21f_3`}NStjN8`Ep3&r7 zLM!>5L?}(;@vfzART(>OQ@z-f|y>Mz$O-m~V)@WcYn6?AgKsGf@z$UZ-MVVAs2 zpBa}H`8$R$`z4l&rCL3s6JkWMJac!Z1>4T2bvz_*(QKyN>MqZc-Ya8W7AyXJY8wVx zm-z_Na|_{1A>H7=9uYE;gZ6^YDv5NQduPRMi-JP0m z7~i6kkB*Fd8CWI+p5cDOrXXuH+oB76_u;_E9EY8c)DN5oC)*Em_`jU&uF!VqeBYpw zW_o!&=Tw--ZJ`z^DAu3?%2c-_fyl_npQ^<`{4|^_Qh)n*rKo5ORB$<=ROvZ#C0RCv zwmn7s$%PA0C8NJp8-TE4m~>$UbLlH{AZnsDRpu*_kkIPj!AlU%cltW~?z$x)6y4vy zYAY&o^QSUBHWDBi0uzt&L6*f?#%=Y;mBZtVn(uNM)x^?*R54S>QBzZX9kFxWR;M6; zIdz%MgtqUk10P0 zo65A!`S?Rh55qk>&StH0*Kb@3Oih2MG5B&>)sfbwR^-9_ww4#YPN}Lb=Dx|Mf5Xz3b?08ZJC3tC zIXyaPxxxUs1bPNiKd9q@;n)CMh5iD!x+UBFiTF19h0JFmNJbPwYL{D>(g90dJhb@%xGsFcrORRhP^YUf9FeHb|0Wu9X* zORhW`toZkrQTl>_z(OZF%WuWhwzkTTcG7qUEu1Vqq<;%k z-oNjHRm~7N<#4N-$l}W&7c!*l*b(<7y9rdmwnd(bZ>puVVCV) zE?*X%w&YAabcujg{__5&>A>bZ#c6bOQZS|m_*9KDY~>pB^W0a9_XB^cn56$!NT>Al zQu$I8`{E8-(trzte>pug1;Ag>`(}I@{Ih%aNegto#NNKsPs# zmK;JpKJ#g#!T48>UP58`>#N7P z6z|_+ZHvT%SSx6cR+1f2_7&aY@?UE0YzB_%+X9p;_vS*+ViF{XZ&`_nH)PR03clsW zAV(sht!zaX__0J?9J1gcH*#|FdTE|}S#_CLk#E}bx3gBNuB@(n8#5L1nCRWNmNsJ5 z+uH_8;Ix6sj~DPQYJ_Tu#UC5^Hd$L3E@kF&9i=v0mB)u5M-$tb9a z>De&}Hl=b_y!B>`3XExIdktsO(}M+?>G>IWQH8d1*r$RK;lvT))kBEdrx>2myGZ0` z0Kn!K6h8R+T+DC=AX_ug^N}cmo`yWYPC)_A9weF`<*Xy|sHCx}4}LSzd6>G)U_p-Q zOXt;QW?k+x!!O!WoWiIqsGSx)xgHwJ@hxELQ#^n!gr> zP97f{)n05iNzc(==us>gEKm7P5mQXv9amL@y5x%#x$4=B8v}%G%wkWFHg5H&fKr;B z5h^k&IKe{c^20mdN_dB8f8&Hv#fn5#7+adRnwIGv*t}%>D5T*4s*wg@<@lX|JLd`c zN$FbiccSaVp_aA<5hNZ&09EhuI37chC)o6Y9_bZCDB77#l?%rJUQM4M&^sV+T@6Eqb%-jG>SpQ4VqN9o_^{1Z)PrSUtfTXMkblmEFKC-&VWJH z@q2x$yOsf0?9ML$BQWrNjOeaRwHM5P7B@w*J31K`+rJb78r2IM8~G%0Fg<}GbBc`o zYk1Zd#N*Pc^(ZL#?dWk)T+LZGP{YThKw1XKVO<*=KMlewTR@HqSk|C+4&nc5MF|B- z46Wu%3B#dek)xg{?&HnO#&RR6j+(;dm1L08lM_P(fwV>LqbEQRVy>$Eo)Uw>Fo+mS zqsd(|2=5J9tP0o|(~DPurDh2!w<+8zm&7|5cy zRhnXER9>9+-`r{}9{XGRLy9#+!B+l0S`|;>PEfOIPDtL}?F%DS#q36ttX$`E*+5E2 zNQgt?LL!yNYgB|Fgm_4#{Rt2q3WxawZ?O0W*^$(#5B|6qO(YC4>1QKkXb-I*BJ+=r z#{#4cXp6wR4|Y4Zt`@uEY0+%7xIRC1T2z%Y;p^E-OFX0AUUru=>LCzJ zO3W6kb8!~#t}CDF&v+9Am-yXX$7kjT z(CHd~#Z_D2u+Wjosxl)$2Mr)NR>PKM-#td?gCb0BA3u&(P^z%(M4(orqT8Pj{*cKxowlg+p9 z&pp)ZX3F5D!l<41txcxQl6^tobpestp;X}a5>JuDq@37%X9{Ntk@kq~;VT|O@cS#S zFI1cs@!_+oxy_pP4k^mIZsWQ+?q?fM=*BKqGS@CB+kGIy8xnR2Bb80Y%ws7KLum$W z#+e($Z@zbTJQ=z!nQ!1wQxp`nwf%`_Co~-v+SsfwYcifTBOk_jAUbEsCJ7zJO+f{x zTxLhpSPAeZdA&vnd%)BvUi0t8i@zz~jX0~ZX@4dvD#igSfo^xEa~p$7xxv+ezEq(v zt^$z$tE;Pv=~B;5Fo=G(`?Pg(fSgBrn)@dZF$IyLeAa}`odY9TMa2$wI%%P!oKsz3 zGu;I@>)Y!{ez-gQNd?AJM}-O20^6NxF{?5g0HplwkKvOC#WrwwPIoKZk5b)y z?Ck$`ON#XOwkICkk}5Yg1V1028+XeVe**fqRI%0>6a+}fEvjYAHx9hAd7REPB{7Iy z^*QkH@Io3D4~Z`T$soN?fe#*si~8}Uf5;A%a%>6hV00X8^Sn6#;O5oSV=vER^o%r} zmoq=Q`J1N2RYehOFq>v-l#5%*=Ky=LGaT&5gAm6EJ8vRtJ!eG&^yQ-Rol0ppkjz@Y z*)-yp#(^Xg&}o6r!azd0e15(4Q&mJ%`1y6nTQ=`AXWTa821_k*5r4(H` z0XlN-u?5C{`2E3sxy!BVv0zAGc(mj4l)Aemk0u>sKJ(O%^V9Ry)63zmE`N!>!QamZ zPp8iBuDNf1JdB1xUYR^r)P7%`sBA}~5Fk5@o;^<_qZYj@;c5SY+CJ^>4X>%a}22Xlf1c*1< zW6nE+a`2TZeJR_p? zfrv(Uy)Vqrev}On^t_wWGoSnUDDbln2wde@+y%`D;foSg6n4!`R zhpOsS%YeEsZSHll+|ZAWPIGKqndGqxRY%ZRSgiS7{0<_#X~I#0|C}ic%9O)%0||uE zaJd{z$2$$N@4}rxdyufO_%%G7Rn{!&zyQoCt5lEJ(%q?6pI}V`{F@6sAWqWk?M>mL z043~;Y`XUHTpf3v9XS;yT^A4g?+A4AsdAmi({JC-HR?WXxmzUwel}3*?COg`s`_FX z7+7MSUS2j{bm0_HP-gV&e|n4FKE7)%85`>#LI)PHp#}4NzcUXKl@jq$#es#QE4`E` z1(1zS<29}3s|jsQy2d+BXhDJU_q3sCktl#qG~Wy+v;#e^bu|HtfPj%kmO8yUSkP4z z!8AK^qnee`|Ngr(H$J}CJ_lJ&_N&|pSp_x3Us)kYpeO#WL@aIV=BxoGS1J%pVriAV z!Ht73Ipir89$vdgC$sl`y?BvKORJ-g za>^3=#DB+5O^gf9U;j2@AG zACW%?%m}tZprvzE?guPE4u=!w9kya(z0uF0(MKD3o^y-FM6Ss{HXy~IR@3+_>dIIF zT`xOWuX(Rpg(W9|j39s%m7_1?T2HO-uBu@^b=!1w?0M2f!bm2ORp0oGKZtkb&#^KQ zmdv>L{ep5xAyc~JI}Zz&ZgL!dvEnN1@;$Fh3koR?P<0|M{5?Z_M_b2JSH zhf6=*zIy+@_2Gq_)X^`@=3h6<;nM1dty*_Jve_9`#mEiwgCNuL8sRA-0)q4Qw2?}g z`CH4Hq!xU>L6EZO8SK>sUHj&&haBXbLGalcfO1RKs-Tlf=8d70J}{7D0+@+jIN#uCXE2CSkF&9k&P=|+ zP5tY8YOLVwCG6pX275{v@Wg(|Qu23E#E2%ur%Hm*09Uo8K(?%or6rleMX=xUN+TLD zpY!A?RaMn|wOAuXvjOY*KJRv3?zyK5;@;LLXOUd)uqnL?aMxk8Y})7kXyrF2!=y_b zc%?>T`~x3QgOoxqdZK`l*=kI`bmV-I#&`1tghM(^ssK2I(>E{-bL|7s{$Id?^>5xJ ziF#U!8Q0gjD#gDzLS`jet)OwP5@k$}V-K+1cuIzyd$f2PqXy?X7g@}0M+_WZ{5(M;-b2Td+Q{xYr zih6tdIfLe86z{(1H>KuGDjJHX;@+%T=!qd-*45<&;E72*0Szw0_3`EPz|ClhI^1R*y*|%N^vK;8z zcNX21EY<9cvbqG93ZtmBBr!QNs;baXYC3BDUt9VBmc4%+^z$Dn5!49@8jv7-tgw@5 zG1tk)qQ1!tu6}rH093L%vay06#p=gemuXYJ#AO z$kRQVz1OsA-yk~%y&*lux-7U;*R;r0hU3^QKz5JENfZ$d5wa4`D6UKC8ME_AYqVgf zVbnW2S)!*%>+ZX(M#&jU7X7r6EA?J2X;!(>{Z)*?L~V*C>p^Ww?F)XX*SS!MPOi=D z^0}{>-L2&;V!l?Q_UQKFNgRIl+phhm18bOT5j+lPaASs&?K*bS8k)XjitVv(tm(3a zZLuDsYehe=lUVI2f%^!0Kzf)$#ZifxOnyL#0+`G;=qtiQHzy+G-kpx zdIrxUpIVqxHrT)G!>!L~GR01ZJ4P`^&K1f0!a&aC z+AC0KWg`VwAmTano+*%_1FqCh_5S(73G^RlyXfUMp7V{~f# z^H!Z55ErWFUBJDOM69}GV471F7Ut&_fSgbHZApV5^2Ec;0u5{B#6;Y|;q@Anm|(%O zh+SusY(Sfy9$e7?awT>Z=fw%1dNO9%mY*FfKB&CF&z~G52J)8m8+@%WO-;=%4-a*KCgR!RC7<%#X@T6xXw|lX!)+fIWW6oas((no2Z;uGc?IOE zq|ngTwEQUYaLOT&x1cO20E@L;GLYnpe!qi_{l2hB|9Y}mrfO%o_s7^4Q5WOFaqIAG z;3~OPx%<|r7};$AdI3t?M2n*LPsj=A&>%qpbW$S|nOA^V0tZ9-{cD}oC+r%s08jj# zWscK$d8e42liNZT(IY5v6W!S0b#H~;*W2un>4V1W*2qgh2d)y`I?ZDwqr*7LTc{>e zUi3GOe0dI$f=fi>uID3;;I_`xd&PSVJ|CBsi{Ev%)jfB$4K9x-E+C0*moO{)_n)4- zo$cwZmm6T6T>Yj3R!6N%@SAy>(7?B+e6^l;s+!A*QGNREF4t!`c>aXX+gRQK1%1@x ze14Ojb~duD?Kjm6w(-ejsY?VO`syQ(7U}<&gn$79gV(#4n|0t>+Z1FmzCR&*`8{W0 z^TXF2A);1)`57RYBodXy(4J< z;eY^0nt5>&VIfHB7&18B~-ncW%(kN25q(Rre;U3nPzm`+dD_s zw-9!sk1u(xN<`q-HuL4|Pu(3`cCT9_h;g~>Hp*+Pc)U`T&JTqCiDrk_Rbk}zIrOkD zkA7mPsgzbw!?^*v@i)riS;NeB)25I}fo^%N@KeUY1LfJLe?3wiN^2>)DT(_hF)*U@ z)qZVQMl@(h^Xv@I;?2Sg48^vNy0+hRE2E@76|^l*E3J$L%e1`~Wa}LwgHn^y}B4ZJd9i<#d_)=_-IW0D7jb>U4c| zZDMMPucU^&94=P7dg*fVkST{O5=_(s>*QZ|QiW;jfQ`%lugt(ic^Wm% z`m~bP`dO9P^iS7Q3=4=}4eY{hXc?IMefrd?Y~gBrIIVvZlvV}@GExr+VyFPU~a&0uO#D*i2>LcTrz;YzGZMwz1gGD@C zXid9H6vV%Q(q&GV@aIg(Lu?L<`G`Ttz0&+q-{fnJVqGBv5E6qpctK{}z!fcUQ9&@} z8mM06sh-$CgApgov|j$iTBHW={XZoOi1(p~5yTH#D-g%t1p8SyEr@{p`^o94&EatR zlIuSgYC*obprFtN_UjSQiGV3vYcf$#D7&$ph%Gvp(*E~dUNWxzdNbq2FL0$zN6)}k z2#bnmjhPx;$I?*8v(f3ME{8pA*SYq@@%qhve(rlpYFve(Cm%1a9Yx?fMrOtCf5FKn zguLLy`|<$}2*g1)o6j=;hxmb$wXvL_D`%Oh1ATFGexQ72gl8@~NbR|bigtA6)t7|z zM3KFV>k*_WWl9o}5_!mTgVeclF-cc9yj2%no`t!-t|=v;=Juy2;Er97s8owSAIQ>! z+fV*kS;F1Hk8+~`)@lA}AZDE~bU;3>y@a`V&nufB&17Kk;IhID2Z-Q6cpfvxj5=wu zSnn+4txT?mx_bZl{Z<;dfp@dgLtbhM4=zC3fzbgB7WJ6Dv!;9AsEYF1^DwUO!X(j( zih?P*W9u31rk&rTnF~@iivAyR2$iiC4GpfFWhhMvB7MRF#h3Pc637Esav|*S$+a4m zkz*mRcI=w+zZCT(#3eh~c`#9I^}LTknA`tYPptvS{fFH{==p)9wJea4Upx3; zu`@kOOMKJ5ldEstM!&YQiZXlvByk%*2Eo<`tM7qg5Jgy*G~SF=IxRi~Jm;!Cc>u3@ z2%}TS^QB?AY#OP6(F?BALuVIn$f6jT^79K<6EHQkTN_g663&RFsER2VCZPQm-f-c4r_aux%7=#Xf`q)anya``%dG5;ewxRi z)xqs*%{g@U;Eq(~;AY?HN^9}1`sVRpCorwMRVH38G2j`m(_lwrO)# zzYqeio_Y(%2B7z0VB%0!Tz)ERx4t#c@|^cPD^gWeji&G57+2%UBqGMZ!pif>Ad*O6 zHW{BqSt{I%tPs?+DOm75MEcEE~^MX|x)hhm8dN{qn2R zKgzs%CHgJ2iNyQna_Qr($-O7f<*&z?GdcnW20=)uO5QE^eksOf#?wAeQ@zN^N%Fdv zrIn<@&A)unj0?@0uvAhp$j%@phWFU8?rY=cKfPRTFIO!tKTUhi*-$U9u9yROY=|jN z0IVULZ!*#a79Ev#k68+}<~;4}iMra7lgiJiS7j|!7-M1-JoU^)Ks-&dn0<}$Djj?< zGo_;8n_Y8}$a%~2sJ%8%N=o+3@P%vNo15G5*;y*J?+Okq$TQYZ)oiJhqA0Dkg8Fhn z+FUsYmQ&U06>J)HPA%ERr}t(2U^7GZB=8(39P>8aLF zYS_Q>Dm!0T$UN0*5O~ppdG(`jeUz%jRYB^$&q?08K-jAJtol>?r-`}oA_JgIbojT8+^y8Pia@dHez zOR#xOM&WqUI3Jc{5=S#Naa<>PAX;&@>Ab9HjBUcD+;DYiX73oA&0N(hU{ zc8 z1L5!-0?K<}XmCqsYYgyyF7OY%;Qf zyh?eBz`%l%Lb=bzc{jH=l@1WvdDqoYReHB-)9szp-C#P?$?<#;jy!4%m@u7?N^>%3G#BQ71`*tO7Psy^0JF1#NfaFpv$Z;k$g%@3O?Ps z!PD={lV(-3>pMGzN(-)HMqHfZb2FR;(v%`;_}rT>k|g8$?4TW>()JebJx3F-E#Jz2 z#lyzWxW;b~;=37?s&s9q1Yj=zeT(vz9JyI%;(98iin(grFYQ*f0<%A|r6sK#Iw*ZM z_ty33zL8m<%eCmonf%wQz4SmkV+;hgM1H5DiO#r?i&UN|xhW9J>*9rnDthGD{onJg|m zuD@41SGPUaXCDY1KzPw`GAn1b615U-cN2ZK$Md5)mbJJ^FEqy>d_O}pa?rt^lCI_h z8`9KyJB^w{AM({wQ@DcC-nc_y?AGl(K|xiW1S~E@{ft=Tm5z?<4bI|lloVg_>}0W= zfkV|X0s=D)Ri9lenTW)|z!e0VI_Bd7d%bi}>SDKHypYUsRpWJk{%(Cc@#cXx6Rim034`v1!ey(nA7}#hT0O$$`2~bdzd@i=I(BvbhC;Y&J5`Zh2>+az` zK0jX!?u}PX@A+y%Mn=+;=hWwI<+SP+>sibyuf6VsPy+Z1l}g4-&KKnD#DZf{p1<%C z6AC9#G8GMi9KP$>@jR;L6FQ!5_E4>JuPageKh0fvG@I+X*RASoZP~jzq3B4XXpOBQ zvQf3EG3L2N%tH;KhEScfH5Q>}YKR2Un1YbD+g4M9A~ZBqZ8e4#F-79O+3W7J*13P( zv(`QLoWH)6H!I)wywCTHzxR2bv{=e#-IU&0$pdXI?9q{G`!*jmfL<#>RS1;zDI`ZF zq&)4&k@e2DDC)*FwY2|_|U#NS<@{n?X&mx zLC`BryxT9r;;iXIbe5sYQed4PRQHqyML5*VME}5kqkRk175Pa=aR>s4_ zmUb2;n|tfhsM+Fpd0(1Y0BPH!e{xe2ij&g_yXd>>&bP%9BFO@27`<%wG6lxAER;|$ zr45xsG?gt0<`cf_ZSxEUb&(YA%kDwzF85xpa|YHIcx7cM)am94Su+-`Zimw!i{GyE z@OA}U-%LtQv^0q!A8~aOBl`r1g&&S{Gr`mnoZ>T9X$R`k1 zIo4y}zq-*FrgF8RXZ}uCXQ%##H3@UQH#gB6H4|7ob!K&K(}L7S_oZ3r1h>iT*lXawrn1O)AmCPhb7)a^EtellIfd^$K zA+)r7e0?q6T;$Xkt*nI1@?OuSFE=bfE~wdEKp+;DmWJ0}@1V)du5&(KewIGLwPQ(5ovRB)cBG$m!VK76zG-WSsj9c!dN4U zU}3~bzMqXW46YS$*W8zIwd9LQveZIj|N1ipg0U^s9QIidI|L*{Sr{-TuDi!gzka{B=nGD#Mc zgyC%(14kPYj?X{7a5FUE1-1~yS~1+(-s$Na)hF}rtl>u|saWBNXV0Fdrqt9#Mn?WI zCqjQ3{FyFTN0TM?M#Y*K84Se1B;f|;*|i?-6-`CgXVv>4XVjeOPAE1_@s^Yf3xqZm!ZEp|HzHEH>#9hRIhY>&*I)G*=r_%DrQjAZH4l$gVo}A~{MVl1O+i`_~dxXukMX}y! z6tpvDaf6{=kY4g)&a2;c1lmLJ1LP*qG`}d9K)SofSo0VeS^1Io^FwGCv!Xh2aYF+W z>rFGa?7~Sz5@OUjBq^+Ivw+O{T{!D%rjv5|hi#Jd5Uckg5a5iTPGE9!M2#sutA4Y( zn-iC?D{5&$=N?L=cb5igt*1`x&7EU!ul1{hj47)S>o2;$IiUx4*`}s(f}IU|pukaJ zOntX&5x79Fff2^|%?X?_T~mUK1QN9=XtyKfQGiVcKh;)Kvqa8 zPi-VsMqDFECq6}jTIoRap`~50C;MfqYp@EuS##;8psfG&={IY%eY)%D59@WsJ4jR0 z{-O|~OYBeL*nD1OXlUX`Qyxb4i3%gC(nInEe{D5M8l=mR)@!3h>Kw)w2ftH=Ff)GeM;Fz zq9;yOZEh}8Sy7ufGS)z^tn7h=sHBfrYxPyFYqpJVerXVD;!z*}Fok7qly^=IRCy1D zj_xpb`r3sS=|V8ez`&Z9XV1DTX5XNT=ZfZ_qju}btafSU0E}Kkl58odfo*bTprDn` zEQlkL@BjK0%3Q(R$JgH?CLj*q%<-|Zv8=?k+5^8JDyi-q5MDF88PP;<^YQb7d)ao~ zkyPkfx3fU97iMa=Y}dQ_qx9*0TfbkUCcBE#*Yc9zqEu!kBLv!Lt_ zN5BVlrBxSa8u#Uu=3bqsc=g0goEB@jsTrA7ur=Y<(=T^&xbUXHP5p3InTxJlNpij> zmK#2h+0}vbVnUjy(`mBoW63B}Q`1SyTHbQEq@-l)o4%F7riCNV7V#Dlh%!*ugHFq< zN=;2A6RP%#!-?b7JC6@Micivfdha}?yKf{%EHDGSzZKYy*D%A#(8v-Tt`rp}9Td!@ z`iLuAEz^<(`3@ZLalG^D9Up%sNZsI*j{;D-557#xYsM=NH{L`|c~7?>BiG;Zqn{Vx zfs%A|yo=1Vv9`kE$(@tu z3c8&gz?ni{N7P9)vBN0yuOIoU=AuuY!0di;Mfo%A`S$OxsH%k%%*_>ZDLG20md2$| zSl<)!mL}S9yC{^3_rpN+0q|9e=kyKsI7ou*BU{phkKAyS){?pr$Kl{A@Yb$-Pe-Tj z%ssMkHrH{?d&kEITGxL~%Sd~15ty%~+BITV{8(626v;Va%~&o+NgueFop#ScNXX!M zy@!u+%?-$p2oNehoO?rXdzO-%+2OZwsuGl2q-O zZjtxh__4>&M;t(UHu15|;Zl~ol{cacgo{0=I&_~oge{p_UVjMUMs#{%&5H`MNChCv z`)!roOxg{kg6PSUr-{8~Zt=;!(Oq{@LEl~+&^m%De`VRmW;eIguIR`qs_RUHAa!dZ zEQ%BZFs0COsF)_g%A?MJ@FPLp!uF+uYISDpz1K3mmB)?=U#O#%de_y~`;L?Bn?lI~ zCdYdE`)we?>H2k$g3U<)q_B6Iv(N=95nUp+^2fzbl-=Wr1v(_7I`td9s?nMxx+qE= z8IvNCY&y0*kBW$&$r`UFI*()3*!|tn8{IL+Muimv-wtYfSNOwLy5dTDUKD7#H)j$N zY23hTI^Oi6x~l!xee7mZr9+@UO+;%k)>J&Wt$6=|13e%s{5;hzaQMd$ak}vbk?Ea=hk6Elnx!LJG zaxGysA~xPq#P6{r_lmLE*(EI>6B3fFe);8| zOeIcJNi3V z(d2l-?8k5<@=vUVA*Sl}{kIR4)RDn4+|EuUh$SO`FbWN=_p`2aj^0LG_`TED(JU3y z3Q>b}58_ZA z$J~zNwI@Y3z|+$kqG^h3Q1x#O_Uh{98oIs}ld0ALA(arRlv z5G206xC&yCaZ0l0a&WMvxkZWZS4w*Oyyd%61A$um1~xt1$_#$i_g0Z;Zmt!;1-}iL z>FHmuXvG$0YFG!ct)NPq*mF zxonCz7!c$`80V_Y=}N2c8kdy_m;rc$tM&dx!2be>w&vkSTRyvLfm&Jy@NQM+?~fqB z^xAZTh>nheu+T6hgjiG*SR{98Z8tk3N2cyi?PrMkj916SJrfWbC46#3TUvS<+UKZF zgr>_LPZ&k;mYtW9Ar}2IL#2*2MK;VnbOBq)Yt^I&^~yO*=82p5quS24xAUW24u|go zcd4dg<=LM<1nvZ&D=vxC-Yx(p`B0#`Q-!?*yvpYg|y+I zjl56t#5C#ixR#eU(v_sU=R>=v?)U_M{hiE@OUZ{DBa%SGb_rm_Pv^aB$EtSd$xs=H zj75=(8O2ym<`UM-%l66Hm%mv#nU~Zn@t4QzlgFQE$VqrP|>N zd4ibV&b6b}74)Ri4fc)j7|$0{yo0~G(;OJUC1y}Ps5=@Xhh&;@xQY$H*Yd|6Ne4wR zAGc20`CHTO`^ofNmI%tch^>L;y2FDw+1fRiA+l7@!lkUS4Q0py;8&eM(0y-vnWl zeKwa;P7GtfwSx#%)|H?V%F@vu#}zld8{FSoNExqYjAmqJ`Py5L6cMU$VOdKw)SMIkBi&4c?B_3*MY=F$Jd-Ku!T0(}(wcYFh#)9$ZRZ&*;+1>hX_$0w1 zl_CWm*LwfHIfW}^Aoj^{vAs6OOdlK!Z7k94G%d*Jb|1_q(!XxUW@qN$0A3*ui-14> z`RB2w7-~vte*8$iA?E zc(D6p%mL*FF5+2*9Q@e|*I?R2%nZ$x|P4E>FHo5yJq0 zcIMd8il)-*b+vWS{=mD7o)bGv0ONv?v104Jh@5?s8NgwC3KY00lk+$PpxPQzAo$_4 zaZ?MIC%oP%bP1&$6Y2(!J&oX$l-k)!_`RRwrQ$wviNq{7Vb*+un)mjCcmu>Cc4 z#Xn@W4;u2l{~{PA{GUSfUoXc4a9VRDiA(1l#1)bwzMc^9C%Z23{)e*qS!c`7TypV; zJhFPxs(;a5wErMj{MWtZzZmw<$kq$F<2S$CUj0)I&~KN5n+MecSM%E`v0X-|0}B98f|4e+~|KA0Gk7Ky)%Ylf6;Ds zpAS&`=E^_3D;^URurT|yx&IOHZ|3{^;|XPVtHihx@VVz!ShJ(|-}hnoip%J~+s=R3 n!M};>M4Bt%=zrTcM-dK;R&};iaw|=lOQ?aK$#uNWt^5B4W|ohY literal 25510 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 diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-highlighted-double-flamegraph-1-snap.png b/webapp/javascript/components/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-highlighted-double-flamegraph-1-snap.png index 69a49487f4924e6ea90d214f7fbfb8d4f825d0c1..bbb7eb615d9dc5309797d6ae73c0b7ea8e24694b 100644 GIT binary patch literal 25613 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 diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/color.spec.ts b/webapp/javascript/components/FlameGraph/FlameGraphComponent/color.spec.ts new file mode 100644 index 0000000000..4c1db80840 --- /dev/null +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/color.spec.ts @@ -0,0 +1,39 @@ +import Color from 'color'; +import { colorBasedOnDiffPercent, NewDiffColor } from './color'; +import { DefaultPalette } from './colorPalette'; + +describe.each([ + // red (diff > 0) + [30, 60, DefaultPalette.badColor.toString()], + + // green (diff < 0%) + [60, 0, DefaultPalette.goodColor.toString()], + + // grey (diff == 0) + [0, 0, DefaultPalette.neutralColor.toString()], +])('.colorBasedOnDiffPercent(%i, %i)', (a, b, expected) => { + it(`returns ${expected}`, () => { + expect(colorBasedOnDiffPercent(DefaultPalette, a, b).rgb().toString()).toBe( + expected + ); + }); +}); + +describe('NewDiffColor with white-to-black example palette', () => { + describe.each([ + [-100, 'rgb(255, 255, 255)'], + [0, 'rgb(128, 128, 128)'], + [100, 'rgb(0, 0, 0)'], + ])('.NewDiffColor(%i)', (a, expected) => { + it(`returns ${expected}`, () => { + const color = NewDiffColor({ + name: 'my palette', + goodColor: Color('white'), + neutralColor: Color('grey'), + badColor: Color('black'), + }); + + expect(color(a).rgb().toString()).toBe(expected); + }); + }); +}); diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/color.ts b/webapp/javascript/components/FlameGraph/FlameGraphComponent/color.ts index 2078182437..9ac60dcd6d 100644 --- a/webapp/javascript/components/FlameGraph/FlameGraphComponent/color.ts +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/color.ts @@ -1,6 +1,8 @@ /* eslint-disable camelcase */ import Color from 'color'; +import { scaleThreshold, scaleLinear } from 'd3-scale'; import murmurhash3_32_gc from './murmur3'; +import type { FlamegraphPalette } from './colorPalette'; const colors = [ Color.hsl(24, 69, 60), @@ -36,32 +38,38 @@ export const diffColorGreen = Color.rgb(0, 170, 0); export const highlightColor = Color('#48CE73'); -// assume: left >= 0 && Math.abs(diff) <= left so diff / left is in [0...1] -// if left == 0 || Math.abs(diff) > left, we use the color of 100% -export function colorBasedOnDiff(diff: number, left: number, a: number) { - const v = - !left || Math.abs(diff) > left - ? 200 - : 200 * Math.sqrt(Math.abs(diff / left)); - if (diff >= 0) return Color.rgb(200, 200 - v, 200 - v).alpha(a); - - return Color.rgb(200 - v, 200, 200 - v).alpha(a); -} - export function colorBasedOnDiffPercent( + palette: FlamegraphPalette, leftPercent: number, - rightPercent: number, - alpha: number + rightPercent: number ) { const result = diffPercent(leftPercent, rightPercent); - return colorFromPercentage(result, alpha); + const color = NewDiffColor(palette); + return color(result); } // TODO move to a different file // difference between 2 percents export function diffPercent(leftPercent: number, rightPercent: number) { + if (leftPercent === rightPercent) { + return 0; + } + + if (leftPercent === 0) { + return 100; + } + // https://en.wikipedia.org/wiki/Relative_change_and_difference - return ((rightPercent - leftPercent) / leftPercent) * 100; + const result = ((rightPercent - leftPercent) / leftPercent) * 100; + + if (result > 100) { + return 100; + } + if (result < -100) { + return -100; + } + + return result; } export function colorFromPercentage(p: number, alpha: number) { @@ -119,9 +127,39 @@ export function getPackageNameFromStackTrace( return stackTrace; } -export function colorBasedOnPackageName(name: string, a: number) { +export function colorBasedOnPackageName( + palette: FlamegraphPalette, + name: string +) { const hash = murmurhash3_32_gc(name); - const colorIndex = hash % colors.length; - const baseClr = colors[colorIndex]; - return baseClr.alpha(a); + const colorIndex = hash % palette.colors.length; + const baseClr = palette.colors[colorIndex]; + + return baseClr; +} + +/** + * NewDiffColor constructs a function that given a number from -100 to 100 + * it returns the color for that number in a linear scale + * encoded in rgb + */ +export function NewDiffColor( + props: Omit +): (n: number) => Color { + const { goodColor, neutralColor, badColor } = props; + + const color = scaleLinear() + .domain([-100, 0, 100]) + // TODO types from DefinitelyTyped seem to mismatch + .range([ + goodColor.rgb().toString(), + neutralColor.rgb().toString(), + badColor.rgb().toString(), + ] as any); + + return (n: number) => { + // convert to our Color object + // since that's what users are expecting to use + return Color(color(n).toString()); + }; } diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/colorPalette.ts b/webapp/javascript/components/FlameGraph/FlameGraphComponent/colorPalette.ts new file mode 100644 index 0000000000..a908d73d22 --- /dev/null +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/colorPalette.ts @@ -0,0 +1,58 @@ +import Color from 'color'; + +// FlamegraphPalette represents +export interface FlamegraphPalette { + name: string; + goodColor: Color; + neutralColor: Color; + badColor: Color; + + colors: Color[]; +} + +export const DefaultPalette: FlamegraphPalette = { + name: 'Default', + // green + goodColor: Color.rgb(0, 170, 0), + // grey + neutralColor: Color.rgb(148, 142, 142), + // red + badColor: Color.rgb(200, 0, 0), + + colors: [ + Color.hsl(24, 69, 60), + Color.hsl(34, 65, 65), + Color.hsl(194, 52, 61), + Color.hsl(163, 45, 55), + Color.hsl(211, 48, 60), + Color.hsl(246, 40, 65), + Color.hsl(305, 63, 79), + Color.hsl(47, 100, 73), + + Color.rgb(183, 219, 171), + Color.rgb(244, 213, 152), + Color.rgb(112, 219, 237), + Color.rgb(249, 186, 143), + Color.rgb(242, 145, 145), + Color.rgb(130, 181, 216), + Color.rgb(229, 168, 226), + Color.rgb(174, 162, 224), + Color.rgb(154, 196, 138), + Color.rgb(242, 201, 109), + Color.rgb(101, 197, 219), + Color.rgb(249, 147, 78), + Color.rgb(234, 100, 96), + Color.rgb(81, 149, 206), + Color.rgb(214, 131, 206), + Color.rgb(128, 110, 183), + ], +}; + +export const ColorBlindPalette: FlamegraphPalette = { + ...DefaultPalette, + + name: 'Color Blind', + goodColor: Color.rgb(26, 133, 255), + neutralColor: Color.rgb(148, 142, 142), + badColor: Color.rgb(220, 50, 32), +}; diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/index.spec.tsx b/webapp/javascript/components/FlameGraph/FlameGraphComponent/index.spec.tsx index 12d5297659..326cedb5e3 100644 --- a/webapp/javascript/components/FlameGraph/FlameGraphComponent/index.spec.tsx +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/index.spec.tsx @@ -5,6 +5,7 @@ import { Maybe } from '@utils/fp'; import FlamegraphComponent from './index'; import TestData from './testData'; import { BAR_HEIGHT } from './constants'; +import { DefaultPalette, FlamegraphPalette } from './colorPalette'; // the leaves have already been tested // this is just to guarantee code is compiling @@ -12,6 +13,7 @@ import { BAR_HEIGHT } from './constants'; describe('FlamegraphComponent', () => { const ExportData = () =>
ExportData
; + const setPalette = (p: FlamegraphPalette) => {}; it('renders', () => { const onZoom = jest.fn(); const onReset = jest.fn(); @@ -30,6 +32,8 @@ describe('FlamegraphComponent', () => { isDirty={isDirty} flamebearer={TestData.SimpleTree} ExportData={ExportData} + palette={DefaultPalette} + setPalette={setPalette} /> ); }); @@ -52,6 +56,8 @@ describe('FlamegraphComponent', () => { isDirty={isDirty} flamebearer={TestData.SimpleTree} ExportData={ExportData} + palette={DefaultPalette} + setPalette={setPalette} /> ); @@ -85,6 +91,8 @@ describe('FlamegraphComponent', () => { isDirty={isDirty} flamebearer={TestData.SimpleTree} ExportData={ExportData} + palette={DefaultPalette} + setPalette={setPalette} /> ); @@ -115,6 +123,8 @@ describe('FlamegraphComponent', () => { isDirty={isDirty} flamebearer={TestData.SimpleTree} ExportData={ExportData} + palette={DefaultPalette} + setPalette={setPalette} /> ); @@ -146,6 +156,8 @@ describe('FlamegraphComponent', () => { isDirty={isDirty} flamebearer={TestData.SimpleTree} ExportData={ExportData} + palette={DefaultPalette} + setPalette={setPalette} /> ); @@ -177,6 +189,8 @@ describe('FlamegraphComponent', () => { isDirty={isDirty} flamebearer={TestData.SimpleTree} ExportData={ExportData} + palette={DefaultPalette} + setPalette={setPalette} /> ); @@ -214,6 +228,8 @@ describe('FlamegraphComponent', () => { isDirty={isDirty} flamebearer={TestData.SimpleTree} ExportData={ExportData} + palette={DefaultPalette} + setPalette={setPalette} /> ); @@ -237,6 +253,8 @@ describe('FlamegraphComponent', () => { isDirty={isDirty} flamebearer={flamebearer} ExportData={ExportData} + palette={DefaultPalette} + setPalette={setPalette} /> ); @@ -266,6 +284,8 @@ describe('FlamegraphComponent', () => { isDirty={isDirty} flamebearer={TestData.empty} ExportData={ExportData} + palette={DefaultPalette} + setPalette={setPalette} /> ); screen.getByText(/No profiling data available/); diff --git a/webapp/javascript/components/FlameGraph/FlameGraphComponent/index.tsx b/webapp/javascript/components/FlameGraph/FlameGraphComponent/index.tsx index 5c46a62bdc..dcf4a9f526 100644 --- a/webapp/javascript/components/FlameGraph/FlameGraphComponent/index.tsx +++ b/webapp/javascript/components/FlameGraph/FlameGraphComponent/index.tsx @@ -13,6 +13,7 @@ import Tooltip from './Tooltip'; import ContextMenu from './ContextMenu'; import { PX_PER_LEVEL } from './constants'; import Header from './Header'; +import type { FlamegraphPalette } from './colorPalette'; interface FlamegraphProps { flamebearer: Flamebearer; @@ -32,11 +33,12 @@ interface FlamegraphProps { ExportData: () => React.ReactElement; ['data-testid']?: string; + palette: FlamegraphPalette; + setPalette: (p: FlamegraphPalette) => void; } export default function FlameGraphComponent(props: FlamegraphProps) { const canvasRef = React.useRef(); - // const [flamegraph, setFlamegraph] = React.useState(); const flamegraph = useRef(); const [rightClickedNode, setRightClickedNode] = React.useState< @@ -48,6 +50,7 @@ export default function FlameGraphComponent(props: FlamegraphProps) { const { onZoom, onReset, isDirty, onFocusOnNode } = props; const { ExportData } = props; const { 'data-testid': dataTestId } = props; + const { palette, setPalette } = props; // debounce rendering canvas // used for situations like resizing @@ -162,7 +165,7 @@ export default function FlameGraphComponent(props: FlamegraphProps) { [flamegraph] ); - React.useEffect(() => { + const constructCanvas = () => { if (canvasRef.current) { const f = new Flamegraph( flamebearer, @@ -170,12 +173,22 @@ export default function FlameGraphComponent(props: FlamegraphProps) { focusedNode, fitMode, highlightQuery, - zoom + zoom, + palette ); flamegraph.current = f; - renderCanvas(); } + }; + + React.useEffect(() => { + constructCanvas(); + renderCanvas(); + }, [palette]); + + React.useEffect(() => { + constructCanvas(); + renderCanvas(); }, [ canvasRef.current, flamebearer, @@ -203,6 +216,8 @@ export default function FlameGraphComponent(props: FlamegraphProps) { format={flamebearer.format} units={flamebearer.units} ExportData={ExportData} + palette={palette} + setPalette={setPalette} /> {dataUnavailable ? ( diff --git a/webapp/javascript/components/FlameGraph/FlameGraphRenderer.jsx b/webapp/javascript/components/FlameGraph/FlameGraphRenderer.jsx index 11faac9695..dd5b0af734 100644 --- a/webapp/javascript/components/FlameGraph/FlameGraphRenderer.jsx +++ b/webapp/javascript/components/FlameGraph/FlameGraphRenderer.jsx @@ -12,6 +12,10 @@ import Graph from './FlameGraphComponent'; import ProfilerTable from '../ProfilerTable'; import Toolbar from '../Toolbar'; import { createFF } from '../../util/flamebearer'; +import { + DefaultPalette, + ColorBlindPalette, +} from './FlameGraphComponent/colorPalette'; import styles from './FlamegraphRenderer.module.css'; import ExportData from '../ExportData'; @@ -39,6 +43,9 @@ class FlameGraphRenderer extends React.Component { highlightQuery: '', flamegraphConfigs: this.initialFlamegraphState, + + // TODO make this come from the redux store? + palette: DefaultPalette, }; // for situations like in grafana we only display the flamegraph @@ -229,6 +236,7 @@ class FlameGraphRenderer extends React.Component { isFlamegraphDirty={this.state.isFlamegraphDirty} highlightQuery={this.state.highlightQuery} handleTableItemClick={this.onTableItemClick} + palette={this.state.palette} /> ); @@ -282,6 +290,12 @@ class FlameGraphRenderer extends React.Component { onFocusOnNode={this.onFocusOnNode} onReset={this.onReset} isDirty={this.isDirty} + palette={this.state.palette} + setPalette={(p) => + this.setState({ + palette: p, + }) + } /> ) : null; diff --git a/webapp/javascript/components/ProfilerTable.jsx b/webapp/javascript/components/ProfilerTable.jsx index 85bf7a233d..5d163f452e 100644 --- a/webapp/javascript/components/ProfilerTable.jsx +++ b/webapp/javascript/components/ProfilerTable.jsx @@ -83,12 +83,13 @@ function backgroundImageStyle(a, b, color) { // - _: render both diff color // - L: only render diff color on the left, if the left is longer than the right (better, green) // - R: only render diff color on the right, if the right is longer than the left (worse, red) -function backgroundImageDiffStyle(a, b, total, color, side) { +function backgroundImageDiffStyle(palette, a, b, total, color, side) { const w = 148; const k = w - (Math.min(a, b) / total) * w; const kd = w - (Math.max(a, b) / total) * w; const clr = color.alpha(1.0); - const cld = b < a ? diffColorGreen.alpha(0.8) : diffColorRed.alpha(0.8); + const cld = + b < a ? palette.goodColor.alpha(0.8) : palette.badColor.alpha(0.8); if (side === 'L' && a < b) { return ` @@ -122,6 +123,7 @@ export default function ProfilerTable({ fitMode, handleTableItemClick, highlightQuery, + palette, }) { return ( ); } @@ -168,6 +171,7 @@ function Table({ fitMode, handleTableItemClick, highlightQuery, + palette, }) { if (!flamebearer || flamebearer.numTicks === 0) { return []; @@ -212,6 +216,7 @@ function Table({ fitMode={fitMode} handleTableItemClick={handleTableItemClick} highlightQuery={highlightQuery} + palette={palette} />
@@ -227,6 +232,7 @@ const TableBody = React.memo( fitMode, handleTableItemClick, highlightQuery, + palette, }) => { const { numTicks, maxSelf, sampleRate, spyName, units } = flamebearer; @@ -301,6 +307,7 @@ const TableBody = React.memo( {/* The `style` prop expects a mapping from style properties to values, not a string. */} { const pn = getPackageNameFromStackTrace(spyName, x.name); - const color = viewDiff ? defaultColor : colorBasedOnPackageName(pn, 1); + const color = viewDiff + ? defaultColor + : colorBasedOnPackageName(palette, pn); const style = { backgroundColor: color, }; diff --git a/yarn.lock b/yarn.lock index 390f801659..5966635152 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3669,6 +3669,18 @@ dependencies: "@types/d3-color" "^1" +"@types/d3-scale@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.2.tgz#41be241126af4630524ead9cb1008ab2f0f26e69" + integrity sha512-Yk4htunhPAwN0XGlIwArRomOjdoBFXC3+kCxK2Ubg7I9shQlVSJy/pG/Ht5ASN+gdMIalpk8TJ5xV74jFsetLA== + dependencies: + "@types/d3-time" "*" + +"@types/d3-time@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.0.tgz#e1ac0f3e9e195135361fa1a1d62f795d87e6e819" + integrity sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg== + "@types/eslint-scope@^3.7.0": version "3.7.1" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.1.tgz#8dc390a7b4f9dd9f1284629efce982e41612116e" @@ -6644,6 +6656,11 @@ commander@2, commander@^2.19.0, commander@^2.20.0, commander@^2.9.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@7, commander@^7.0.0, commander@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + commander@8.3.0, commander@^8.2.0, commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" @@ -6664,11 +6681,6 @@ commander@^6.2.1: resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== -commander@^7.0.0, commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" @@ -7614,11 +7626,23 @@ d3-array@1, d3-array@^1.1.1, d3-array@^1.2.0: resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw== +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.1.1.tgz#7797eb53ead6b9083c75a45a681e93fc41bc468c" + integrity sha512-33qQ+ZoZlli19IFiQx4QEpf2CBEayMRzhlisJHSCsSUbDXv6ZishqS1x7uFVClKG4Wr7rZVHvaAttoLow6GqdQ== + dependencies: + internmap "1 - 2" + d3-axis@1: version "1.0.12" resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.12.tgz#cdf20ba210cfbb43795af33756886fb3638daac9" integrity sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ== +d3-axis@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322" + integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw== + d3-brush@1: version "1.1.6" resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-1.1.6.tgz#b0a22c7372cabec128bdddf9bddc058592f89e9b" @@ -7630,6 +7654,17 @@ d3-brush@1: d3-selection "1" d3-transition "1" +d3-brush@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c" + integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "3" + d3-transition "3" + d3-chord@1: version "1.0.6" resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-1.0.6.tgz#309157e3f2db2c752f0280fedd35f2067ccbb15f" @@ -7638,6 +7673,13 @@ d3-chord@1: d3-array "1" d3-path "1" +d3-chord@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966" + integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g== + dependencies: + d3-path "1 - 3" + d3-collection@1: version "1.0.7" resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e" @@ -7648,6 +7690,11 @@ d3-color@1: resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.4.1.tgz#c52002bf8846ada4424d55d97982fef26eb3bc8a" integrity sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q== +"d3-color@1 - 3", d3-color@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.0.1.tgz#03316e595955d1fcd39d9f3610ad41bb90194d0a" + integrity sha512-6/SlHkDOBLyQSJ1j1Ghs82OIUXpKWlR0hCsw0XrLSQhuUPuCSmLQ1QPH98vpnQxMUQM2/gfAkUEWsupVpd9JGw== + d3-contour@1: version "1.3.2" resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-1.3.2.tgz#652aacd500d2264cb3423cee10db69f6f59bead3" @@ -7655,11 +7702,30 @@ d3-contour@1: dependencies: d3-array "^1.1.1" +d3-contour@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-3.0.1.tgz#2c64255d43059599cd0dba8fe4cc3d51ccdd9bbd" + integrity sha512-0Oc4D0KyhwhM7ZL0RMnfGycLN7hxHB8CMmwZ3+H26PWAG0ozNuYG5hXSDNgmP1SgJkQMrlG6cP20HoaSbvcJTQ== + dependencies: + d3-array "2 - 3" + +d3-delaunay@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.2.tgz#7fd3717ad0eade2fc9939f4260acfb503f984e92" + integrity sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ== + dependencies: + delaunator "5" + d3-dispatch@1: version "1.0.6" resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.6.tgz#00d37bcee4dd8cd97729dd893a0ac29caaba5d58" integrity sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA== +"d3-dispatch@1 - 3", d3-dispatch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" + integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== + d3-drag@1: version "1.2.5" resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.2.5.tgz#2537f451acd39d31406677b7dc77c82f7d988f70" @@ -7668,6 +7734,14 @@ d3-drag@1: d3-dispatch "1" d3-selection "1" +"d3-drag@2 - 3", d3-drag@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" + integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== + dependencies: + d3-dispatch "1 - 3" + d3-selection "3" + d3-dsv@1: version "1.2.0" resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.2.0.tgz#9d5f75c3a5f8abd611f74d3f5847b0d4338b885c" @@ -7677,11 +7751,25 @@ d3-dsv@1: iconv-lite "0.4" rw "1" +"d3-dsv@1 - 3", d3-dsv@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73" + integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q== + dependencies: + commander "7" + iconv-lite "0.6" + rw "1" + d3-ease@1: version "1.0.7" resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.7.tgz#9a834890ef8b8ae8c558b2fe55bd57f5993b85e2" integrity sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ== +"d3-ease@1 - 3", d3-ease@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + d3-fetch@1: version "1.2.0" resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-1.2.0.tgz#15ce2ecfc41b092b1db50abd2c552c2316cf7fc7" @@ -7689,6 +7777,13 @@ d3-fetch@1: dependencies: d3-dsv "1" +d3-fetch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22" + integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw== + dependencies: + d3-dsv "1 - 3" + d3-force@1: version "1.2.1" resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-1.2.1.tgz#fd29a5d1ff181c9e7f0669e4bd72bdb0e914ec0b" @@ -7699,11 +7794,25 @@ d3-force@1: d3-quadtree "1" d3-timer "1" +d3-force@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4" + integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg== + dependencies: + d3-dispatch "1 - 3" + d3-quadtree "1 - 3" + d3-timer "1 - 3" + d3-format@1: version "1.4.5" resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4" integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ== +"d3-format@1 - 3", d3-format@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + d3-geo@1: version "1.12.1" resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.12.1.tgz#7fc2ab7414b72e59fbcbd603e80d9adc029b035f" @@ -7711,11 +7820,23 @@ d3-geo@1: dependencies: d3-array "1" +d3-geo@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.0.1.tgz#4f92362fd8685d93e3b1fae0fd97dc8980b1ed7e" + integrity sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA== + dependencies: + d3-array "2.5.0 - 3" + d3-hierarchy@1: version "1.1.9" resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz#2f6bee24caaea43f8dc37545fa01628559647a83" integrity sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ== +d3-hierarchy@3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.1.tgz#9cbb0ffd2375137a351e6cfeed344a06d4ff4597" + integrity sha512-LtAIu54UctRmhGKllleflmHalttH3zkfSi4NlKrTAoFKjC+AFBJohsCAdgCBYQwH0F8hIOGY89X1pPqAchlMkA== + d3-interpolate@1, d3-interpolate@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.4.0.tgz#526e79e2d80daa383f9e0c1c1c7dcc0f0583e987" @@ -7723,26 +7844,53 @@ d3-interpolate@1, d3-interpolate@1.4.0: dependencies: d3-color "1" +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + d3-path@1: version "1.0.9" resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== +"d3-path@1 - 3", d3-path@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.0.1.tgz#f09dec0aaffd770b7995f1a399152bf93052321e" + integrity sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w== + d3-polygon@1: version "1.0.6" resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.6.tgz#0bf8cb8180a6dc107f518ddf7975e12abbfbd38e" integrity sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ== +d3-polygon@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" + integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== + d3-quadtree@1: version "1.0.7" resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.7.tgz#ca8b84df7bb53763fe3c2f24bd435137f4e53135" integrity sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA== +"d3-quadtree@1 - 3", d3-quadtree@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" + integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw== + d3-random@1: version "1.1.2" resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.1.2.tgz#2833be7c124360bf9e2d3fd4f33847cfe6cab291" integrity sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ== +d3-random@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4" + integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== + d3-scale-chromatic@1: version "1.5.0" resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz#54e333fc78212f439b14641fb55801dd81135a98" @@ -7751,6 +7899,14 @@ d3-scale-chromatic@1: d3-color "1" d3-interpolate "1" +d3-scale-chromatic@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a" + integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g== + dependencies: + d3-color "1 - 3" + d3-interpolate "1 - 3" + d3-scale@2: version "2.2.2" resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.2.2.tgz#4e880e0b2745acaaddd3ede26a9e908a9e17b81f" @@ -7763,11 +7919,27 @@ d3-scale@2: d3-time "1" d3-time-format "2" +d3-scale@4, d3-scale@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + d3-selection@1, d3-selection@^1.1.0: version "1.4.2" resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.4.2.tgz#dcaa49522c0dbf32d6c1858afc26b6094555bc5c" integrity sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg== +"d3-selection@2 - 3", d3-selection@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" + integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== + d3-shape@1: version "1.3.7" resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" @@ -7775,6 +7947,13 @@ d3-shape@1: dependencies: d3-path "1" +d3-shape@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.1.0.tgz#c8a495652d83ea6f524e482fca57aa3f8bc32556" + integrity sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ== + dependencies: + d3-path "1 - 3" + d3-time-format@2: version "2.3.0" resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.3.0.tgz#107bdc028667788a8924ba040faf1fbccd5a7850" @@ -7782,16 +7961,35 @@ d3-time-format@2: dependencies: d3-time "1" +"d3-time-format@2 - 4", d3-time-format@4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + d3-time@1: version "1.1.0" resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1" integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA== +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3, d3-time@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975" + integrity sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ== + dependencies: + d3-array "2 - 3" + d3-timer@1: version "1.0.10" resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5" integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw== +"d3-timer@1 - 3", d3-timer@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== + d3-transition@1: version "1.3.2" resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.3.2.tgz#a98ef2151be8d8600543434c1ca80140ae23b398" @@ -7804,6 +8002,17 @@ d3-transition@1: d3-selection "^1.1.0" d3-timer "1" +"d3-transition@2 - 3", d3-transition@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" + integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== + dependencies: + d3-color "1 - 3" + d3-dispatch "1 - 3" + d3-ease "1 - 3" + d3-interpolate "1 - 3" + d3-timer "1 - 3" + d3-voronoi@1: version "1.1.4" resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.4.tgz#dd3c78d7653d2bb359284ae478645d95944c8297" @@ -7820,6 +8029,17 @@ d3-zoom@1: d3-selection "1" d3-transition "1" +d3-zoom@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" + integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "2 - 3" + d3-transition "2 - 3" + d3@5.15.0: version "5.15.0" resolved "https://registry.yarnpkg.com/d3/-/d3-5.15.0.tgz#ffd44958e6a3cb8a59a84429c45429b8bca5677a" @@ -7857,6 +8077,42 @@ d3@5.15.0: d3-voronoi "1" d3-zoom "1" +d3@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-7.3.0.tgz#f3d5a22c1f658952a6491cf50132f5267ed7a40a" + integrity sha512-MDRLJCMK232OJQRqGljQ/gCxtB8k3/sLKFjftMjzPB3nKVUODpdW9Rb3vcq7U8Ka5YKoZkAmp++Ur6I+6iNWIw== + dependencies: + d3-array "3" + d3-axis "3" + d3-brush "3" + d3-chord "3" + d3-color "3" + d3-contour "3" + d3-delaunay "6" + d3-dispatch "3" + d3-drag "3" + d3-dsv "3" + d3-ease "3" + d3-fetch "3" + d3-force "3" + d3-format "3" + d3-geo "3" + d3-hierarchy "3" + d3-interpolate "3" + d3-path "3" + d3-polygon "3" + d3-quadtree "3" + d3-random "3" + d3-scale "4" + d3-scale-chromatic "3" + d3-selection "3" + d3-shape "3" + d3-time "3" + d3-time-format "4" + d3-timer "3" + d3-transition "3" + d3-zoom "3" + damerau-levenshtein@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" @@ -8088,6 +8344,13 @@ del@^4.1.1: pify "^4.0.1" rimraf "^2.6.3" +delaunator@5: + version "5.0.0" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b" + integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw== + dependencies: + robust-predicates "^3.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -10953,6 +11216,13 @@ iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv- dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@0.6: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + icss-utils@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-3.0.1.tgz#ee70d3ae8cac38c6be5ed91e851b27eed343ad0f" @@ -11184,6 +11454,11 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + interpret@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" @@ -17293,6 +17568,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +robust-predicates@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.1.tgz#ecde075044f7f30118682bd9fb3f123109577f9a" + integrity sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g== + rst-selector-parser@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91" @@ -17392,7 +17672,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==