From d50c8b41b73416b1f99d98513bf8300336955b4b Mon Sep 17 00:00:00 2001 From: Eldar Iusupzhanov <84278206+Tucchhaa@users.noreply.github.com> Date: Mon, 31 Mar 2025 22:53:17 +0400 Subject: [PATCH 1/5] CardView - columnchooser --- .../cardView/columnChooser/a11y.functional.ts | 22 ++ .../cardView/columnChooser/api.functional.ts | 44 +++ .../tests/cardView/columnChooser/visual.ts | 43 +++ ...iew_column-chooser (fluent-blue-light).png | Bin 0 -> 13178 bytes ...w_column-chooser (material-blue-light).png | Bin 0 -> 12106 bytes .../etalons/card-view_column-chooser.png | Bin 0 -> 12901 bytes .../tests/cardView/etalons/headers.png | Bin 0 -> 2367 bytes .../grids/grid_core/column_chooser/const.ts | 26 ++ .../column_chooser/m_column_chooser.ts | 25 +- .../grids/new/card_view/main_view.tsx | 9 +- .../column_chooser/column_chooser.tsx | 46 +++ .../column_chooser/controller.test.ts | 192 +++++++++++ .../grid_core/column_chooser/controller.ts | 65 ++++ .../new/grid_core/column_chooser/index.ts | 4 + .../options.integration.test.ts | 304 ++++++++++++++++++ .../new/grid_core/column_chooser/options.ts | 12 + .../column_chooser/public_methods.ts | 18 ++ .../column_chooser/test-utils.test.ts | 128 ++++++++ .../new/grid_core/column_chooser/view.test.ts | 124 +++++++ .../new/grid_core/column_chooser/view.tsx | 215 +++++++++++++ .../grid_core/columns_controller/options.ts | 2 + .../new/grid_core/columns_controller/types.ts | 4 +- .../__internal/grids/new/grid_core/options.ts | 3 + .../__internal/grids/new/grid_core/widget.ts | 15 +- 24 files changed, 1274 insertions(+), 27 deletions(-) create mode 100644 e2e/testcafe-devextreme/tests/cardView/columnChooser/a11y.functional.ts create mode 100644 e2e/testcafe-devextreme/tests/cardView/columnChooser/api.functional.ts create mode 100644 e2e/testcafe-devextreme/tests/cardView/columnChooser/visual.ts create mode 100644 e2e/testcafe-devextreme/tests/cardView/etalons/card-view_column-chooser (fluent-blue-light).png create mode 100644 e2e/testcafe-devextreme/tests/cardView/etalons/card-view_column-chooser (material-blue-light).png create mode 100644 e2e/testcafe-devextreme/tests/cardView/etalons/card-view_column-chooser.png create mode 100644 e2e/testcafe-devextreme/tests/cardView/etalons/headers.png create mode 100644 packages/devextreme/js/__internal/grids/grid_core/column_chooser/const.ts create mode 100644 packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/column_chooser.tsx create mode 100644 packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts create mode 100644 packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.ts create mode 100644 packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/index.ts create mode 100644 packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/options.integration.test.ts create mode 100644 packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/options.ts create mode 100644 packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/public_methods.ts create mode 100644 packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/test-utils.test.ts create mode 100644 packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.test.ts create mode 100644 packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.tsx diff --git a/e2e/testcafe-devextreme/tests/cardView/columnChooser/a11y.functional.ts b/e2e/testcafe-devextreme/tests/cardView/columnChooser/a11y.functional.ts new file mode 100644 index 000000000000..b8a7ed48ca1a --- /dev/null +++ b/e2e/testcafe-devextreme/tests/cardView/columnChooser/a11y.functional.ts @@ -0,0 +1,22 @@ +import CardView from 'devextreme-testcafe-models/cardView'; +import url from '../../../helpers/getPageUrl'; +import { createWidget } from '../../../helpers/createWidget'; + +fixture.disablePageReloads`CardView - ColumnChooser.A11y.Functional` + .page(url(__dirname, '../../container.html')); + +const CARD_VIEW_SELECTOR = '#container'; + +test('column chooser popup should have aria-label attribute', async (t) => { + const cardView = new CardView(CARD_VIEW_SELECTOR); + const columnChooser = cardView.getColumnChooser(); + + await cardView.apiShowColumnChooser(); + + await t.expect(columnChooser.content.getAttribute('aria-label')).ok(); +}).before(async () => createWidget('dxCardView', { + columnChooser: { + enabled: true, + }, + columns: ['Column 1'], +})); diff --git a/e2e/testcafe-devextreme/tests/cardView/columnChooser/api.functional.ts b/e2e/testcafe-devextreme/tests/cardView/columnChooser/api.functional.ts new file mode 100644 index 000000000000..5f1a73eeb508 --- /dev/null +++ b/e2e/testcafe-devextreme/tests/cardView/columnChooser/api.functional.ts @@ -0,0 +1,44 @@ +import CardView from 'devextreme-testcafe-models/cardView'; +import url from '../../../helpers/getPageUrl'; +import { createWidget } from '../../../helpers/createWidget'; + +fixture.disablePageReloads`CardView - ColumnChooser.Functional` + .page(url(__dirname, '../../container.html')); + +// TODO: refator this when cardView is merged to 25.1 . This should be in ColumnChooser POM +const isOpened = (columnChooser) => columnChooser.element.exists; + +test('public method showColumnChooser', async (t) => { + const cardView = new CardView('#container'); + const columnChooser = cardView.getColumnChooser(); + + await t.expect(isOpened(columnChooser)).notOk(); + + await cardView.apiShowColumnChooser(); + await t.expect(isOpened(columnChooser)).ok(); +}).before(async () => { + await createWidget('dxCardView', { + columns: ['Column 1'], + columnChooser: { + enabled: true, + }, + }); +}); + +test('public method hideColumnChooser', async (t) => { + const cardView = new CardView('#container'); + const columnChooser = cardView.getColumnChooser(); + + await t.click(cardView.getColumnChooserButton()); + await t.expect(isOpened(columnChooser)).ok(); + + await cardView.apiHideColumnChooser(); + await t.expect(isOpened(columnChooser)).notOk(); +}).before(async () => { + await createWidget('dxCardView', { + columns: ['Column 1'], + columnChooser: { + enabled: true, + }, + }); +}); diff --git a/e2e/testcafe-devextreme/tests/cardView/columnChooser/visual.ts b/e2e/testcafe-devextreme/tests/cardView/columnChooser/visual.ts new file mode 100644 index 000000000000..f41bca9eea68 --- /dev/null +++ b/e2e/testcafe-devextreme/tests/cardView/columnChooser/visual.ts @@ -0,0 +1,43 @@ +import CardView from 'devextreme-testcafe-models/cardView'; +import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; +import url from '../../../helpers/getPageUrl'; +import { testScreenshot } from '../../../helpers/themeUtils'; +import { createWidget } from '../../../helpers/createWidget'; + +fixture`CardView - ColumnChooser.Visual` + .page(url(__dirname, '../../container.html')); + +const CARD_VIEW_SELECTOR = '#container'; + +test('column chooser in select mode', async (t) => { + const { takeScreenshot, compareResults } = createScreenshotsComparer(t); + const cardView = new CardView(CARD_VIEW_SELECTOR); + const columnChooser = cardView.getColumnChooser(); + + await cardView.apiShowColumnChooser(); + + await testScreenshot(t, takeScreenshot, 'card-view_column-chooser.png', { element: columnChooser.content }); + + await t + .expect(compareResults.isValid()) + .ok(compareResults.errorMessages()); +}).before(async () => createWidget('dxCardView', { + columnChooser: { + enabled: true, + mode: 'select', + height: 400, + width: 400, + search: { + enabled: true, + }, + selection: { + allowSelectAll: true, + }, + }, + columns: [ + { dataField: 'Column 1', visible: false }, + { dataField: 'Column 2', allowHiding: false }, + { dataField: 'Column 3', showInColumnChooser: false }, + { dataField: 'Column 4' }, + ], +})); diff --git a/e2e/testcafe-devextreme/tests/cardView/etalons/card-view_column-chooser (fluent-blue-light).png b/e2e/testcafe-devextreme/tests/cardView/etalons/card-view_column-chooser (fluent-blue-light).png new file mode 100644 index 0000000000000000000000000000000000000000..50f1a51a6783e8310bf3606c3d4a396e33372579 GIT binary patch literal 13178 zcmd^mc{rABzi#vJCPO7;%AAyWCMr|CrqDo%OevX3WU5q#%!*7YM5KfYk*6}xg_2~R zl9}XDVxQOBx7J>JAMZN8_3gF)*vGN|NcHgC&wXFl?>c|y@Dq4QM`Pn3+x}R#Y}v+x z2UPW!En6N={;XSrS1wVc>+si#gR1)uyDuNz=F_xnnS=!S-`ML7#vf*1FDfUYG38_@9f$9tj!;Rw&cH9PPoeAzgAX$^lQT1eGBbCMx+%PV z{aTidmW_681+%JZ>Uc(G=9`h(-r0+SyLaDDPF`U_vwZpTkG9gIM~)mheB?;a%)Db! z$JOiCxw*N`gSkXS!(YAH``KPbO-*eJ6O)0FQJ~lw&m%_|@g`MO)l>QH3=9l%@o(QA zx^m@;tj9F(ty{Nl<8xQ6T$$5877!4yK<{6=@6@U7xH@xDht8QZJ8)rTHT;b$-0to^ zg{#<<4mg`7=m_9D&w3nXMcs$EiR-?Sr z8%=%Y`2=(lwo6Lh{4qPyoUY5chK@t)<;7Y0s``4XsorugYL7pgtmCrmR!w7Lw%sS5 zTfV)!@7tGmDvZvT9H^Wi#0d4 z?lx~okaPX=_VNqc((4-+eza23va*8HwBwud9Zazea&mI1X=%Amed_x9`tIX}Lyq!^ z0WGWDQX94@`zUhyE{KtvH%Qmv+qpBy2J2S*>wCM_9mUvpDH=2RlwToVzMT1*oTzX? z-2SsH);U(fnl}Hl^9Ct)dDj39PVbwPg#nSW^71KaUl@-*)5i$;VLv*hQzIW9J+*C% zlye!xre#z!mv&s}s;`a`Xe;qnXlrXz)zC1o8>qQeJUFIwJxOd$SY>HThQUEi&Cdj) zC55$*rJXEtQ=G2id1~Jg7e~vXSe0dzNBxo#R@K;8Ip)^<_@n}dM?b^ye0yzeR%zQ) zD2&nee7dko6(CY8Mn`GjhIufYO4Ku_wPyJ@Pc+`WpZ{NO*f()#{!9CYm?YB!w-9o8Gwc8hk1O%*W82C9svHtOGm{&kxroC%1+GYJ8 zfAo$QO{96wjRRm7wu+c&?cKX9UfS->&`d;R_>I7Y zQaa_j6AmxSH_Ci|uG{Ev}rqhfcl%a<=db?D-tU>mRF;yZ4t>ra4r=9^{XDo?zw7#q)C*-CPv0< zE!t}`qVOE*=mqxq@t+Rh)DF#%_n>J>b)0WKNwxd*G;k?Z$@|Bl=3B>10!_0`UOvch z>Z_o#@40wWVk4VucpNHus>n72h>6iKG2vLfdiA%_w$0hCwGD|1Q+aK+ z)DG8XZB;cjuJbYM8BxJvXsmiCVq;^ed;$V4Y5dx8-7&XrmHX(^?^ZOWaQ^ES9}f=?cSVlJ zB|mIzrCF_Qno`%BdQGi1GBPrDDrfxr@2IM)Prp^6%du;hM&seYc~(d14maK3P#-Uo zo)#QTvta*Xn7?6QvZu7ACH3IuRQo)h^ZEe2F5jg+^Yim~rYVD4(b2s_&V{lD=<7aM z&;?`}`RLFpaFBkdSf_1qD_iv~=aPr%$&i$JCa$ty;6D_n5x^{|AT;1ZC+CV9lxZ;C=w z)N5C-9y(!?9dkpk{kh##`-}5Jgp63o#sDg@@at%4)1-}snaGnQXp`IH;^HbW7GC)C z&p&13o0{|&_V3^S;6s6vMVeOZn+cyeg_6Y|=cMgFS0$_6prY0ru#9IuJr%^;*yNnA z;(0c0+ZI%%YZfj)3|uR703X11G+1GsKl}U~E1s%grQ*YSVj?15$BK)KPoBfOhs^Wa zryf3da5rt`T3Sc37rjA3Us^IYucc)>h4&@gsO;-m{5dfceZsy6Ev`jfON$28V0rp< z@65ccfx7w{AMH3vE`I*&lar3(5)xDMUI~IcJS!xExWwq$fJDc$?kpXp=<};+@z(B96tQy%sXy8 z|9*UIewUAe&r8p_3g*&WtJ()yS*dAwiIsA~zVMn0;I>?ZhsQ5&aXNEdxh!p91mshTBD)IJgz$RWJ z9WcWneY(X!mjTa$682sC*|mQC`W|!F_eYLR0qjNHMh!{r;L-l93}s(WOUtjI5U;EJ z>n4~o;Tfc1XE7_d?TVLi7z`A+(_Qj&Jmp{%KZxihnND}V@NjxO=YeNA7L~akGpFyk z_pS$sD#b~jeS=$Z?+cMxw|>1Dh%dF!Sol-ELnG)%J?P@_r)NSqYiLZJK0ocad3XxP zp0`f|zc|sP%+W7`nZ>T)3i{~nXf&j~h3)yyj6(jsUch-1j{(M}rY6H@HjG7XW1wdx z+o1_kQ+YYOCijgO&**^nKR65az{|@!S;6Wcdj9KSFC|XYVvq0QkZ-|Ur{_EuaNG<` zrufI#hYP(-lviL_508nEX4zHZEhr)~WZsgZL5Gi_&Ll0>p+|pwdUkWVPGT}R4-K>E zr3fC4CN#Y)@JWmJnMdjp`3d-_jU*CmIr!eWo6ygd2P34 z95_$~me3Ml-7Gjd;Pkga?eja_Sh=lp=NH#Qog5ecXM%*Adn*K&>aKsPT>jS|?4tN8 z6Cq@!tEGjvr#`2_|Nf7z^mk&(P52TJP3MkcVC%^J%*;O+80H%#D!LtI*U`}l$jaWH zsc-N&3Y7NoQ3AbPwHEvZN^5Z@Gc$9??%e}utz?ye{Yj$<)(}HzD4RBIx)KnOpj^QW zoSYQewX1Bv*-43|ArB`Fu*%KtYz8!~sjZdkq8W;994bAX$HmRfbiMvG+PzZ=%m21U z4QdsAQ%}y19Q{7tQ44?w3=2yKb^nYiFX*sWRqgLRHN>3@hV&uJNTu=4ol(25# z6&4P?dUciXc^n2F8JQTp6m>3cXTe;Th>u{VID0%GXZ^N##)9Frcv6<2#CM;ga3)^P zaSRU+C&)UjK#2f3ynlYbj~fjLI55U6ya}B5zROUr7Js)eiXw-yNw$2{;8?Co{nzFA8T?*U;hdtxr%k;9Z9=STPOg5 z@q#{Db93`2AQ-n|V)D>6-6lH0TGj^!29gVd$1LRLl}&&#<^f_8V4lds^% zoPLhw^I%;>jd}O0sK`O*EBAxxVMDSWm{OFIyuY(lhH<8+5!7a959#{){-K-~RkW`n zq;GyGiJ)xpbd31hdM7qLEDZ_;dC$(bHe*!uvf&b1J`l%;8bE zFm8#S70f0V2_)=sE+qWxeaX_ICp0usl-P(XD;Ir*UU4wY&4_IXFVW^c=cMAWS1- zV*`Qnz~H;46d$k|@W#TgnGdTP8q(6fkF{@RWxdfn+@IH|l%nEK%gfK->s&~r*cWhb za$RtZw|UmO0L3$HxqN6-{ey!z0fJ9lA_}0HZbPd>q@_UyCJev2ywbL-BoQ~uCIlQ~ z*>h16*2F2Wa&-0S4<{TLwr#6{KGCwW;)B>GE0{10MFSwq@m=yk7ptzV#c9$zdQ=@! zDkB4Ed04@1l$pr7_ix_3DHwk-@?a}FyS6s1zh6+$AF8UttKEb*p*N+bri!`@YW?^= zrWqrAavcp#Dl7`pkO0?o6trUWikzL?+*i;Q-`-PMyM~snDwsur)IYqEHxsRtMX8P3 zB)hc=3k!+Z^2FpgKVx*8Q66(uEeLW)Oi>G*MEEPlt?5K7QyBJ;42DbTqitpWvPT zwCu@P#ly9YjRNpV(BgnKt){+v-hZFyg1{d%#?Hw(_pf`e$U)bh?=X}WZ@*u)U*CF& zyBSn&n~Z%O@jPZ;t)!cT-kZ5$x^P83WZRShj-Df^58Q>l;2r^ifv-nqbFCXWzK^z* zLQhPMfGm@mi||#DV?AJ}y}dB76T)saOe8ZiuA!z30|6pDrCN##EGi~Jm8MV&dWMDv zu%=|u@ybBlxyP@wQK2_)-4a71gEl?;_U>}JJ>Tf}?c0X}c~|IS4e1rwJe&#)`3z-S z7cUdmYT_Bfz@zS%CT;i05uC5ny>DYpO${NhJQ|_ER_9YQzcvrOTm1F&pq5s@@)$~V zmuX1?Hi(Ctd&w8nO+ZX6Vy4814~&Dek_xe$;NaFE z5mS4uw5Qv__a`fA_detW>0ujaX$OOZ9^ds{T12yHkWpaT3q(KL@j?oxZ~k9w!GG5{ z|KT$J7hCaY)mgdu^aHU)H-c06TGaJzMIZXKMXT%W3kYc8bL)S4v(VSN<`VCZldLLs zwp8)3r23BXP-}TEZv7bM{-?ny_rDcMU;p&=f*lQuhGqf%9~(BD{gA~%jG`qwLccYm zcfFn{9J*rxUK4Pj!(2o7c5bft>Bc+tFmMR+Rxm#<9Nb2F9?o3ZwWn6KTQ_aqd={SC z&~%%1l9(6Ok(}wJ#fc?uZv7~BxrdZd#hRIsxd^AHSK}hhPcEeSZr1-)u783!Q{dyE zxREz+syaD|5m$>&adMe2>^hMVQ$K}z2Onus?i>$qL$Xx3iURDM5W zQG+xs5T+|Ycc*r{{Hf8r#>nVsbv3osJ_7>-gzf?+=$V)_fQlBCp?o4DVU5a532|Ut zMqurP8iVA(#jglu*MwP-qdTP$0TzYK{RZ#^c02h z0zWt(lVkZ^D3JP4W6`OpDFXGMKN~-H=xP9msW8ypqvq-==?iZu1H!eqH~~c6IV~Z9 z?eUARJ2Qz%gVPKVSsm-_?CdDZ25jwiE6Vr)vhNclLRp9;dL3GYopSp&^9#4Jn(2XB zkHJ`LdWNYy9wuWiFGb)4devln*TQv$iQ*^%V9+&v`Su<1$Df{g9gCBZv31Lqt6fBc z!)mrZ4wD~tuu!y!sSaWabgSgJ){%i)5lTP2r?O#Jga;Z8I|VmM}#=0m; zkil~>nHlrjwWaU}yh3o-u2d}f)vH&@8Z;%VZOCMY9J{`eRo?(th2ZMJo!?ixvGuTm zWA`%9L|#DSl`AXYumuJMy>UQEUA=bg-LrGY8t$j2UWL$@!PYfBIw6zk@zMnPvJ8Hy zE_^)(2C*umUpQ|#b_s%lAIcqm$lQDWwKW@b(UTdhAjxZbJsJjfEXT2DKU_8~aD*xN z(#&MrBqWIO)O267kXXX*iV0^wJ~6AivnRf;P76F0AUP1KF#f7V$+E`Kgd;e; z0Eg+MURQaKnR=PnJ)Y9KO7pyMq(GVCWE>i>-oI}Wq89QSlZC z`xT5lE|SGYaC1v{DRZeRz6ji$=V`81mJ%;3R)lEjeBeGE&7ku+J++E9=SpKdc+1!D zaO<~zjA&k*K5$NdaLoMU!=<~@*n_N#sT=Y0A?$Lyx#VxNH@d2;s`_mEk6F`yu?zfd zUu^Jr4)R7Cq9(x8E7#=?A3r}NUJU2|txpI|a08q2feR58AFpZmk0{6>+hmWb>eo#Q z&YyrbEaH~ypvvz_!w47yk zr<$s&Q=P>gw(ZYDl9RcirH0=>WFjyFkkTZ!L#(LT3RrD@BiR&~f;`+YG78SG@297` zfHyUv2u*zEt?;($x;o48&xHgE32lVgAj}A0T7Yqs3aCV1Gt&?*0HPDa*2MSMc^IL< z$l%8(i>4o%{tANNdY5@b2o$xfzdEX|&_w`F6RIGT=qt1n8z5i`${%T4~>H~tCF`#OunY3SnH^5=Jwz!1*{suu-E z0m*}|;?yc@14F|q;^?3yP8843a_h@5_g|5B{X*~geYEHGTFx?N743WX?(H&sa_Q)! z6&2-Y3iYGRi?&VF6`ZLa zx1zw%(7^}|4l@vMkVd@|=p8hiN^Hb_?QNy_`oeU_-AZD8VT)#>CYzvR7I5+dLPGd} zF=*p!3hxr94H54`I6xjEPXnIxdtgdX<4_;5jHBDf_<4C(QP6D`(1SAu9c6b238fq- zKKJT1Yn;Ef2&$@Pvh-iEX?eilW9mK2XbrD!UJN(0z>G8|3|b-KM*V3O)qa1hW)QSL zsk&H+wLlMTjxc|cH4(=iRGr9XU~NV;B%9cEp~nSR;t+aG3E}fTL60DoPNH#st&QLm zg(7BIMgQEsqo(tvXIp_2kIHo#F7Qo`Jr^Cvp0ze1jZD)`(t-D@5z1x;rccx{^tKHS z1dq6QB$Uw>3iMt?TwKjH{X>WLg5tvrr?SKDML&dUXNahcVK3}H{@k`2Dl=B<+}6$f zTEJX-PEG>xMB5=wqSnK?5;RDAizWcMg8pjx=IZ){dX#UhwB0tax*n1Zfk*VA=M3(5 z|1q47h$rO}LcV}5a%@FUE#r3fARZKPgROhsTr+f9`Zbq_zCaH5ZwQgwt)z5^gcv7a z*>MXC(=tT7s0dB?jzCz#`-ki4`ZzVavdYRC5)l7}KFD4(@cqk}{Y=5ALbgengFbB8vW1?Nl}JdEyW@P} z!Qs%Xv@f1gNBKx08kzZYE?dmJY#kcNq^7Q}_1t&|PIUq*J_i=sWxxdh$NDEKnBnCT=ND{x5c1XvzW8Y8%XmWaNPdpB2)}jfnkghN3kwTYDI8WH zNrqwJ?*oaob^+~Z#?(M2$%pdWoeGV~x^7pF#k#^HL4eMg-WJE?ruN8l!R{z(qM-fkBDBaw)*LlV(~3 zy8@89hshmfOgliCXTX3%GLj){G1cmtmOw&yVn}(U$2@ zMfM6dxgClP^e*qhgvrq?Loy}=BNKduft|e`wpeiM2#RcSI6Vo{^C~QWH1O0betvT9 zliPi;v#`mW?~wo<-5?@7d@oj&j43fP_RL=V3y|f~VfHro;|r#I>e7>ZYGBjI;J7;# zbzn-N8TE>`=kx2wtOZyBI`uLPE5VEzhMQ;Y(yT4>*TBe~J36YWtH73eIG3nvhfZMN z1eHVe#yCQYE0VINEF%d3gC(q!H<$z>Q8y_ZxCoa64xBXq?IxtNSWI4g*%IA4!iRy1 z-+(-bB-dS$j8(DzWuDVBWSj#~RWScHKmK2YVz?RwRuxQa@_Ooak^zpnPR5?w)K>q) zx9Aj^=zbe0ZZq;W(AnO@V=dEhKo>|&AB;S7bjs_{glNxPwuiJyyV9Q{_asRRcw)+f z2Lafki?d(L5wl?Vy7e(Vu!fiyiwi@_%}`JTcQtmMWoD_md__F#fUYh{5bwjZFJ73g zEvu+NfmUPEWqz`hj+o!*3C1?)4Ulm>J9eyNC|qcZIL_Lcp=9C7*EChA`^3B{^{=EK zh9SEJjSucI@cS zgYTtbpoRF92=idB1#goI!Wa%2!a$Y>Yq$>wC+#`ha;PVqqbH~9w-K*lVSdKwxh)Hb zu@!oZ*L1ajZO02nW&hIG@N9+=IpZi;U}UK-NjZs(zPJ$2oK?o&a)CMpPJSvp$@Wa8 zyN`@$AaSk6{W!9!s;gg<%$_sy&YcD@ERU}l=>QmFuOdQyg2WOgm4SFkDMPY7H3Z*@E zU9b6V=#&;mcv<(crZ(@len&9QL&1oc59WnvXTQEDw9N+G5iQ7xI%#H8JLa|-L6s>m z#^>F;cZXeM*$55Z4QqtZMv{(L=V31~>WJP0E=B9NaAR+g*_6m*E-vwP6tWBAqJjIe zN6nAvFf4@va(d=4mEa_eG@aAH#H1k%k^2I3e0@bBY)+pb@Ink4Rg!rD+;|SpQg4VZ zt&5r^y+c?@v{6Reg8ivYf-VJ%;X2ih~RePIR&ZgrtD&i5EJnQ4{+xhbIeH z|M&DoPt3p5T|8|jNOkWq`2WxR*3vn1k=A>STOkr9{xA)T_*LY~P2d+8A0Ubz=>-{lOm992%@C{PEl*Mx zz%J1!CEh=giS5VvCP70$aBx4g3?FLXH%ktx9q9G?+1BWzPDXYF5tDZ<49bvaV<_}$ zi*Wf-p1dc4j!ai#Jy8eM@|~1@i={`Tn~?B^UKOIBg~jUScuV%O}NwmrWq@t z3Gz z+h|*!|5{EjdJ7t$BH^|5dH}?uR z;r*DHCWCV`DsUgrrpw3NK&>&=dKYYdp^tOvZW{dgO>AtzrkEKqM2JR4^aKD##2&oR zxMz--&RJPxqJvB$)E^YMrE&;%oS77486tO8`&!;gJNAgw-H(KPi z?GP4D!{@euscAd|FhO5lGsRpKi2x-XyZ4gJo!C!=Mx=rGBP+v<0%!ow0-0Ir?dy|^ z0+sD?d;+5DGhb^eZdJ1d@k>C5{SZQE0Zc;0;n9Z3Bv(Ay%(?OUVviZ9abK%~b>)?n z;4!R&b+LY!+2BWGu*>hLz%DhShzQJ)8CWuH`t6&mPbS=2Fslb=Utd`bzc>Oj(8!B4 zwV_l}va)FY+EW_LS@qUbJ4CV4T0LZ+R`90znQnTQBH?35NkY>;?L1M z0{+;(MQWw;CNgXQR<40^u0Wk)5TqYwcQ*zKVA{SK{3+0o^6TeZ6zsnRUpU;l=H|p| z75^tztK%J%Fue0=Uwpw}8Hs6o6gR*lC@5f_SN@G11dp!I)Q!2hz}5Q4M9t&ri!T!t zJt8qC+H z{rzjL1li19@>>*;l%lwGKw67B@Rdwvl3%mHTu(WihVGepD3y6ZGU>Bp$14b9NAM=x zkWUa|Gy^@o%kbvFR1Gkf5)e>DM}B?eFClmxF2XBJPk3YaaaB^IKL%j55&Oe74hK~s z3f|3v23!xo9m*#62ETHEUEH-inKCt~UFJDMR3wyS$WWvr(lbg%r-zc^>9bJB~J+r*E_;{CM+qUvB#r{L`gE7fB z=^i>_Ml8`a97f%5;+7}Uf>h@{6faiiJo>(OeRfCx2k(*2g2`*w1irNA>FnIOpq5)x zQ!{sx?jM(s5R;y+@8%{Wx^W|QcR0@n_wp^Z0zyKQx?wV97ScR&Cp8ZoSe516^MFdF z&aOH&-2QCIk|pE<4g9vATh7K7&Ht49+%8ScnuX_Z&0+>NHnwFfLPA0-$V+&);4?+* zRcvf-k8xLD@V{{(XUB^-MaRr4d}OQw=_03pj9k~dy1nMvGnu3HtA2g^eD0urMCptwzNd1 z7rlCA82EeGs>q(kDc)6RzudfpLSEJ1d@mfVi>cGHJy>wMwA0NdQ zwRz=DqI9=+Z@{+WFM`Jl-3Rvt&d>DP(VCiS3MIvb zg@s+`W_{CqKd!BfSRY!~e;rZOsXG0BvEjjkW)HojK7amP?9`R8H&!${D(dlrQ^TeY zJU7i_$&bG&6!GqMTlTXzNR5Mmm8a%i<>{pDr^G`-Lhe|U$Mn}lzRoq47<(`*T^qix z&YS)zBl4?{a#@e_SosiN?t`i4JLs>|=g!yl+f03I*4(|@@J;jvZJ()Tg*U|~*iU_F zy{;X}H#-p-R5R#q@CJ{d|E!vCzI)^$BQx_2$Bw(*r^hRcoqLjVr7bJ!XX#UKN}Sd$ zTgfLZEgiw9;&8Wk7w1r3XX!SjC`9I0%_So`oGT`Flcn1o#(l=#%&5e!ZbgEm z+0!4RT}-U3H}TZjUmaChW03UBmX3)u9E1qwC7j7 z-!-Vs)Aiq$IE7YKsh$2gWdgSQ0&#w{ujEEXUc=p#CcKv&v zpAE%njg5Wj^Rr^HV)`E+&5UI{#qQFZT>>?nouxVCUEVc)Y)&ylBrNBYymsPsR;Rpk zcm3j(%E2AOH{JScw>iCyLmU-2_iRTPCCNE*a##j@H?|D=eM&ra`>D&nXMPshK4bp) z{Ho5(kI@{;Sag;fjpip1peoB_&zRy}ab@YQvuN z_NF68ky&lw&*Y*K6EEgjR{Hr{ZLXS?&B@7Wy=@YS-E%_}d3^h1;LvpC3HH`^q@b=7 zL6u4cT4)4?m%W~1bt-X1VCd|Gpfo&N2$zS$#x zC2ZPFS*%T#Zp!iYJ8MNmME0jDM(eBnjvJ&UPK8>{o^?Sq1m^*QXAhK@mn;AJl)=KU zn)>vqx@92UzWt6__2eMU_e;(#*K!O0=?@nrk33k@l|J`P3>l+oV4Krov zd2nijygaA5ySpqNRqWUivFTveDt7kjM61BP_|Piow_JI%VocPh@QsgsXJNNCD+Qf&8 z{Dw&_L;Y`#r4K&eF<#T#%O9N{bMM|3LqkJuC3oQs+7ZGcB1^mKqc=?WRZ3b`T)}s_ z8>;18>67-9xw$!ie#`vCNY!7AUFTM+*5{SJ+c*05KEi=@bH&$1C5WBE6R$<@7C#(& zu$)$S56JK`OLrZmw8v|m)7#=FoZQ@dTGCVs)&qQV8CLM_DROAOx0Hb)=E@c7=+_U` z{#=oD=b8&81G7t#&`buK3rGk*3Zbw zDx$2MdMiCJ`B2_r8}kC&r6nq-e*hRS;dLiGM>?b5zqcm&&*wY9MnS?2_B{*je13Ju zMJa@snwlEc@KpaxZGQV#nR`tWLY(N6gPq$?eW`H?nlV>bS0|7csq%xnBw*%8bbP#) zJwe~rYy)KCd#{IV^c<$;%kAc7=_uT?4o%#s*jgt}Y{Gx%LqZIWm{}~of3mF)@qq6q z19(;auT)ehQ+ghH-zxn2)fH8+p}yX__fY^+@}fiz%2cBytuF=R$ji>A=7z}_ajsew zJc|4Mxe{q1dBw$X{Njp=R~k>YZjPic8$aD}TzK{z0+y9pv~i-m5>{o_8rS@>pNZrD;0dz~<*z zPbUgxbGAW7b`$qGgvzIv8O0~tE;FN0Q)gSXG&Q$)eB4jsjWS*_wF2zI=on|m&WzpR zie4k!T$?QiW;Tk8-#FVfnk8P^6`ptPT5x&{w#)9J&xDYP1`?p;?S03C@m-^}2|y!E zlraU@=AzCRUcYv20g0%2d-=gHehA_t`e=z6W^Z zQE(3H8vO`Lqf8%&4dYkiV>>f4LP0GiR1oO;Sl)eL55Yo&D#9ycyR60H(r)+VCAul{ zZkTHBui2@V0yzNgaDG+V@ZE zMnHd1mpv9xFhUuM8KP&n9(wd`@D1C$*nK?iAv+Bf)YYXXgy8j$~sMFTg_TFe` z!MR*!X6B6&5*hS!4Qp$&(NkDqB7vO_HL zD*LQT=@_<0I#z%vcGgDnN1_gv>=>_L?@Cqj=mgg*VHeXQ)yvxPZSkf{moE9I00Rtc z5Iddw_U-c-&MQ?6np18w@bujF``7ns6cZMCO6N{rU!{^G54~i3Cy!DVGqAkBu+I7Y zMcnYTB=EN%YTU(+;XyE0<)7UiNA2xxbns1kiIX{*6bUXQF?SbM)ORr6+>zbOFV|2+synL&R;8c za!o@+!?eGuX5b1e6gU3HJ(3n>QCJ>v;75V$2ld9rM)C!TI0ep*V8l(liRFj6nQ^fV z8_v!Bo;lc-ANXB@#7>AdpYM5)&)B4-29msz*fK6Fe>Pg-w0v}Q^tZ8|lor*QF!11n z%~pDdO6-==v8@hG0%BqpzkTz>3hNsyyz|*W>WvMe}7mR zbPa)J*46xlK zC3Vw#{9U)-a9-!wqZwxeo6pcy?<;uh>s$J_3K73pGB&!B>%$(BI-ql_`1tgU!I8;& zfU$!@d^yl#YO#TdiRsRfhY4DtoYBe2`!Ee`!7acY%lhp|U`_Gc=B3hr-wISoe~feF zU1bW87I$kJ8m>m!c|R}f*e(e$X~;FcO`?eK@R^aKrmH&=i;K7A0>^j?{ORt{1ht6x zHz3r5gM&4-wX&}7cV1vwd)D4e@%tog^J{=^3FXaG%#MkfSx8Xu3e{ry2uuD2{E zAWa&Yns=qrTk6^z${I zrESLys)-d46Y~^RBu5-f9`cZ#ogIqa;s~c))695P3;D*XN)=E>sK3Pn&r1lksDy-C zfLGEMn?>O~a_Sf{Unq~TlvH@->7T3l_@1L`GObvVrCt}Yo-h{_!aJq~XP5E$1WVX- z+&u#28$t$jOK&}j>E8YOg@uI9&ff?BhAghm+#9=!t-PH@u6`&zC}NbWYI-TgYjlbx zRr&(L4{6(oLD36HojtpBIpI!KvxA#I_g1NaG@4ii#DiW62u*r8WD8DCO)0tcEdhPl z=JGDp#iKu5!FGq|r&Vh0$jh?NSt;Dxj;|v01$Y_8s}vIzwF=-JOs#K8(qbhtCNJ>! zFaJbjs|}4t>#xHa2@qy9`}_A=+(`ga@$?VL@v3>%i!1qS3niV)J}_KZ$*%|dqy)9E zz^0l3^rt0h>#^gV_XL3;gIOugPrZJ9JCUWIt~WpTo1`Ww(x?NS?fF(M$n*vpEyMWs zAtc_p&Q4SDt_PL_|VjVpcP(5Kw684?ZsZL}*fJ9{H#ojm1zf23NLRaIc|@t0@s+>s>J2;yv~zrS(`bh(`w zCxSzG^XAC=jvYiVKwV!%oE4?C`DOF@)lKYS zkRSr#0_(b08QLom89Dcyy5uAH)tWi3%EWW!6Gdm6!T8JU=_qd3i);@&VmmE_D! z;U6P!s`1SgmDBPtmiiK_W<{U}-#=c631HAh$9o^CAQA>U3+&EcxbO;93=#GiMODdn z67^4{Q`+j$etYntn@?dyZA5@!GL08jtltL?$U&?)SJy2ZCp+%yVvIsUCMjC1?ns3w z$oH2S+P+YvpWoh>VCC8N9vR82=o*arLV>=&Sypxhq`^ak*fV6U$Pd;W+@lUenHXc6 z#Krp_pIJOR=3SMMi!s`m7awO6(@)Dpy+r`5>ZImi@K8ndvsYcqIa)i}_ znGC(Su0iYuu(MUGR|A5U$jHcmhsw&z5&;f_iqX{_%Qn<3K7F{B>1O(7T}d0Cx`$;Nb=Y z)I1U`^X5$%_$+_4Vd&;Z@52?|Sw9Y5*qUda*wnP2cp(S%RkSMoz8?qkyls-71xF%P z**69OXmI%OJ}AK6T5b)nKGRA+x$j@vGB8#+LsNr^RY#U85Xo=K+%~{iKtk})3K>~ggdvAuzpBp9daPc(n%IyWH*Vb6 zQcHA+*XUcVyupA@@^(X?m?UZ!qOZVr%E9mZmk`u1B~CRr>BP`S z0W;VslZ5|XRsYwPwp;w~QI{Z6qbo1+2avukZSQGQ$5gu~FwW_v)s_ z1&AEwjO*7d?utCtzi2I|v!IaSYwntYO*8xIB{$aPG@W(N8j;wgnJFquwM$w$IBSak zDY}hyE2RbeF#GjmRA=bz(ix++oY2`pNeUjt6dO(Xkc>&<^Bt zG$I;bw7j@uwv~dbh}awW`0*89OWc}dd8d8q>Wg5S)^T!hJcH!Q0UQ|Lym>P^C51K~ zG=ExkZrTnUy$)vSC2A{$A;%4(v>N{U6=h#pmq&C__=9or@!%M{;Bpj@_#lj@DOoNQ z`oRq*c$VJPMg@9T?_4bw;R;O4P)?~nSj+pbZs#yRc~Ttql#r5AQusQB)ffUyF-Qx- zlL&%!xl~;x4ll^tBO)d~^*mHS@nPZK65Mv%WP^|#*@c{gw`2o;c@nP_Es19Q=;E;) zoKlDXI856;KkbC6aWHGY4c0v_F77}Zs{S+vs&jG0dTMyMePi4vN_SZ_7{VMZV;P7L zl15#l4ztq}L^VL|{WP$&e6GzOpb64a(BswRL~ejhqM7MX6eaO=M}@rF`TNCG{^~+W z6t70Wa|5hif@vT!l4gbHu^-W~u^R9jAxMq9Ao9f@f(yW578VnWO-=7YogAAIkIj-ey90 zX%PA~q-#*ZW$AMU+DzQ>RVI^m1n+fq@bUlaL(6=wprD}C!w4i)AL5QSLg7Ed2Cs@v zrm5d$bUeY<(Fm)w0bQ9lAY&jmS?X9wCHDbF=t8k=+t#GFXv3w*hJU{k;Ff&{tP#b& zZ;B4=T25+9HZT>Q$N-kbsKoloqSfr|<#WG=>C&KK{<9Nx#NX}qe64Flir3^o196W* zgoK3TVt1WP1@OOwMM>NmP^veN0(R&mNZL&FJ!9e7#%RZ~VRx7{m~&=UmOHZAp(U+3 zN>C%ak-M78w&BXwV=EA#sXM$Q;OuTiouyP?TsdSl|BGv#f^#O61**nGqeMQ8#)7t7 z<52LpBH%o%ifjtvIaMtvO~$VF#Z4Wq2cDnRi5Iiob0b340TqY3r`cXmP7eec_2L7P zWd~AS5j&QFYJr|pxS+-b>y&LLR)d&>T!K*R+u90kuKc#T_b8lDlxs{!8@&toDiz;e z>2&)29BaN~R^)>fQSu(+g`>~}xDnM&wnm?XAKTl9o`D^PwS zZj?v|#2N-QU@~V#-O&C@=y2-fAL+yqG{J&yiO;B9JQ4?_{g=G{tARChTu3ws0v(Xf7hSKoBG zn!UmUUPLS0vuBSrL<$&OZZf*Rpk_m8COrN4-S1LFgeWu-tZKr+ zh-`zf+y_^C{SL3AF!f1O0swmu#w;Xs5@NUn5Re372KChm!o#{wegJ)rtf2Whqd~8S zzJvute`yhrdyA0(z^}uYFp~2cF$MYtJE3HtNkS|i0?Nol(p=F)l_3UU``sg8U>+KAS6&}`BJ}5 zO=YMP%?pxjfR-TIemYA5iXp+l3qa()!sGx{MDgUITqAXf8*4l@)N+jU0bo96=N1>Q zVPm_+Vwiz8&8vJXHArE7QV-sj52aAZX3np zf>K4wOroXVB^Z=NP~LN2FRHzOj3B-o>L2mt6sqWiE)1ahDt~*S;W^fwgh%IIj)-u8 zS%EG3FhwW5Vm7v%M)i{wV5>6TV-}=$c@*8VJ%%M6Dm@R)8e6;jhvQ+Y`?>Bgp~w_N6s$TrF6tNPWJe;hr<9bO}Fr@=HW zK_`gY0xI_nmOC>{TT*^-EAh>AQH^%NP5At-az_cE2{dpMV)6LP8%u=@15EdXBSAoU zgf?xu)JRU;Ahu;{tuami$p$f;qp%LUj#3Msds!k)%Q!t~PRZBTx7&Bp zO2-lJ^{DOFK_C!}ZXcW0f}l16vl^jf>T$GU`1@)uE^Uy*0w=g=;InLN*3>|VGs16! zgtrL#{oUwPHLC)#%EY(U9e-6po?pl0y@~ zsDnmEn#NdoVmmOyv%<{DSTr;JWa{PE(U}EI!0Wcygv?Emx!{5g(TD0IKqM@D9v=Mz z?{PigFl+}!w)N|Ei9m<31?_5qg9|X<$*xnW*RYnTIfleBDl1bwd-m+77uOf#6b+VS z;s{pM6nqXF33EYEs4aBY-Am}U;VK*z!7T2sLED(_ullGN)R{aUXr8G~UIm_ZOYiDa zCNyou(IG{bnEZmftB#Hi2aE%mS_Jd7G>!mWzjrSRc06iWO(sC=ewbe*3P5Dyu(3F8OxM!O&CWoem2;v0(fM(_|nR<>7?=h4)KNV(4XTS=)BbqO|kLtG-7+|VG%y1PYt2Y2*L`>#kgU z=4OXQm;LME7#h?tvveYkiG|elKk1)vy-)b2Kj<>CW5N17KD`jcxdIJSQ*Nol#n&Ls z$Y~2S;i+f=dwhN+Lh=X7B^!3Iu^e_6KEmbDP`r2K?fp>4n^+BU@%i&hNHxX03Zo>@ zN--Hh}GP15v@@@#+$IF*5!*W@M^u1O%(O-A)p_daT{8eIpb4@hhH`l$~0*Bcs zf34>HO_cgSJjh+kSD8;7K>+HND>-l(8H)Zv>)O9i)2@~~P|^;JOfGsCuSdBBx1DPv z0WNju=fYKW04hdC#+|Sp{>NJ&|D|yJA(5t3J6go)q{963Q2nV?ubByog+TRFDNW6j zJj>lEjgMB#E^l-bFS?crcK`%;!p;e&J31^+hlho+{N=?TeR`gWI9`!}I2rrKHDhJ{ zD{^BY0ivR#p8%p)MSpoF5Mj?5H)Z$dfB)coM7e^wPoq=#42s(q4W#S_)!DBaq_Imi z(r3t-fB+;L>VxL(=dRMtfYSap6Dxc8u7vC*XCr`!Sc9jEZ7c*?K#LqSRp!`pUUA2F z6-sCsh@yNDua-2fto$dICfJk1V@*k0iPI{F69dF8hS3?)44edbfU-g?+5sB6U8`A1 zBLog8p_4e1WQwDO#8rb&3R7w8iC4lDa@q%|hGQ4^-1>K;4_}XF_I?Onx;&w%Fy%>U zN6Cl#ft=52a9T7?3zxq8r@dlmsE(tDIVW-Gl8DhRIL&bK?O-=Z9xkSWCdr~ToVrg( z#}4`q-9=6u{)0~2C@Faq*O0@84lv&D9KL^C(VCy zFO)|udJ(RD5j(~NaH0)VV~cGKBQ~tgE>dMToON;*5t&GO^2}g`AJa~cU5ES(TfZX# zIVHPwYfdgSBY7-*nkWcsB)V+9oJ_gyg4cbEe5H!ww7nBuZ!TH7)CR3B{}kZ*3*Z3&t^1D)xoB|;{(VWQTRcqFq$N8?a1Z81U;s^*xf9_$pK_JN8LG!<rU?V-9|s;+w-(4n*cH_W3`f|0fcPfX#M=SAlg< z0(I9U*4Xn@LA(?Fa|)V!IA693NM#IY#d)szr#hP}HTUji;_w>je4;itu@al50p3C= zLOn-xYj-+Kx*R9EjIRq*$xzqQNgv9BeEWpSPh+d^CIH2VLWjcm1d@RYSn<8x+;jA8 zJaW-y81=0RN99am(yOLNUgYzmV&B-wyD>pY(|f^iV{m|tSW+F0Fkbf9!^C@5C<)zu z794=nU2E1iXp=K7Qmtggwbr`%@rlj_mNd!1mpvjDy3p`;I4uWDDjsJ@Q&3W2Q4k}A zV{S6BY75*YbVb7QTzVgoOI%1F8CkP-i}eEZpU4@o)?DM|Y|)LRL+n;__^_t&*8atG zyWs_tf6Q)f^SclCL90&ya{a{fmL#f8FN_?M-laKkt5N-KS)ErRdUgko{iU`ev>yJR zE`TBjVrw$Ejl3z_i9ZxMMt}6FO6o^t7kSrO= zC`mv8iIPzygMg$rx7B^C?|t3l-X7z|fO;O0Or+oxamsmsY9k~=IuFSWY*#tl1}nYLD4i=Poq-0d}Sd)VkaX1JqIc)gL{ z)mgP9V4xNsWh8Rn%gd`+!M&chq->fdRw!9bK}Ud9bkC-B26IK@YRg&07^-3wF6>{M zw?_Xp=!sPY=3_c|4rV&c4d*Apq_s1Kfpr8X*!%5SAm43Ce> z@6Ax4Fr05;jVh~(YHyX_xv4NGEq9fUz-8{wD;XIB)H5gENA4GO*GPG?X`-);Pshb& z9fd-P>mHZhl{4GH7cAv@aUftb7Fhmu;PK|7;UX7hc@^G2SE8z5cx_eL{Czg8igPcX zL0o?WBcs(@+`8-LVL7?tz;(yXtDwQXlqI1!2?5tp^W= zxvgfPP^=R)Q$` zz3rD4rgsSlY-gi;@aU1;Yu((8zR-&qlXb@#8E3N+&1FA*`qb*Wv|#x;`8U6^q7qg; zfm-%s<^;bt!MjQ-sr)3>4lUWQ{T$rnme5IM<;mPe1?BPL^Wjpkq`JB$JmZ826 z(Xub~@*~qOHtw_iuHmvUsMl?q%^2|G>(d}z!*YL~Ys0M}>brLDHta6F-+HxZeJZoJ z=;RkShGdfp7LWBDrEUz;iaI)+{GnlCnpxL&xy}@EXH2&{IrKh0=jG=YC)J#Oi6eh; z>h)R%hJFUunUz6$E)uUE2L@W>(I!ecuJ}KCR2*T~e%C8iX3yD|U;JF>d0ppPI_wu` z`<0F#@Al?AaLvo2{+ZRxs6ot=C+t#=`!5y5+|R)+EL$@I+H;+RZTgg{6)_@4bPu9lfgB7wI(2 zBO?=K*Y4msFkr5=%Iz@C`pv}%V`XcmO%nh4tVbOS!*-GrmBQcKbHn(K2Vz@}Vx!dK zR877&B~f*Af=j$v)lZ!|f;TfWGkbb^K2Ub-@T`tFIMHO}C*<_QGTrj??T(SSi;W4b zHZ@XooA-MOPV_uftNZw|_=@YCwm|;8wd$h>4+`tmWU5jv>esAVfh0#&@Z(1?Z-#O_ zNZ{$qmp*sytlF*|{PttKx>cr5>dsxe4BB%XESppBzJGr#CMIT}@ijLV^;9iNI`yoc zUX9+;&vOkgHD#@=gf71c8*a&@SOIA$-Y9J>GRVK&(PUO^LV2EkZ*#OV4~+iKndK3(_e>mT2a? zNU^iC<9h~s`1yPL!mjj9)X4OQUQ93m5L_E+k66zkIyzn<_%I?u1v!@f?Ai9=jBfg~ z2|Dlmd1Nz&vjzt`@@1TUd?%Y~pQ|g7@nwbOm7Fme6v0*{B_$o#g(*4?Q6HptpuqWK zE-uoIx=#E8LEeC%8rMY|U58#~4?6b3o_7y3M+<2`=Q@dbv+z?SCBtb2b2fx^jF{oN z0HjeAlJMnL@#K`0*=oByH$|tuDaXw5_j^7k8mufSDal#*(L%>99UdIaX6Z@4g@TMq zPTrTCoNWK&v)NtX0KeqY4=!qRx$l;PiRZ1~@rB<-iT2e*sg1PfIv^JkskALKW8Fff zi5EWYZg*X}LBqgR>AIUrrE9^igdDUJ5D21e0f5MIxz1aOS~k5M@2#-PZfkm`5>|R+ zx=jI(hJ7wJ)nr-Cz-9b%@~e*1P+F?EBH}b#jlTk zIgI=JnP@f%WcF-y8Fk}Mbey_iZEc+>HQj1+`t<2hf}D)JM?V-AdodE|lbrgfo-@D0GRcii2D?1ptDxfuBKCL%@> zooB7@-McqX_mmbzNN~q#BsVDRa@JiIrX8w14cb?FGy5Zr3h%7FHt=D2MRMXR?Ki#> zHhumP5%<03^Sipb>^t3AGltSzn(|#`2-@`a8dOwO5qNm{k{WsAhbDo%;~t{clLIH6 zrMab}{DhN`_eY{PbeH*+B~!IH#4dBD+jZOsO0mErW#|ZK#m2=MaqKf*1C(GvA~wCR zsF0`~sC{Db%4vGIiJn`!GM@9GEuA*1((2o4nVIE*Cbco=UhA?MiCg!qNkY_w z9QEU>0@Qv*OwvESIA_Em?JVBg+xsXeNL^P~)x?C4;O|-*H_MK^EnyYCg@K`=$82py zDdS75tgH&Ux?CY4A&(wE7P{2D-(|j=TOIH`J>2H-x14*WnaXHHS5;LN9uM@gY|FOm zmm?2J&nf=)^P})^<%ppzAIfMYsEV!T+0LI}vd3oLZWEO*0uBP9>!ExNcfCpCv9A1s_ z@u9O^P0#sO)a3mp^npU)JKKKq4M95AYw_W2d-ixY{1|HSywsXu6|QVyvFnwIvGG=l z9#vX8(qW>{s^!v~BtWXArlzLk-1n5?vN9V1jnshH*lj;XI@A!Hq@<+qgsiLsmb$Nl zm=I(A7cX9PTP9Pz1r0S>;);@~;m3|0E3_T>z!Sa>-S_mjZ{HFfa&_|*<>XeSlkZ)> zejSuX-=|X!)TN31^VDD?I&e2P{#(*t_&J3h%cyyy!Gw z_u&wu*G8I&h=_z&RtV---WO{x?<(<5GBGtZ+_Q7%7dd>ViLj}68iDToY;<+a(XyU1 z2ac(z@PYAlbs6fq%$le^d-lvDYH>1-^n{;39joQgcZGz6(1bUxa~H48yD^uDt=AuH zc*TLrAf1e9sO1fVc4NYMiGYgU7`u`7R;#it^Np?xtVmOAl2JuvWpVnAIa}4!XU@p) z1v6ExNir(S==MEGy6U@k?<&K@{O}|J;o+5$QcmSnRlPu_R1sN@uV@%gj^2-njlFYl zB9 zXm_4a$x9f{oz`u=ET$$owhC>7BtQc_mt;9&UyV2f@3+`UcJTUaFRABh?6JiV_QnVZ zq2oMOBB!8Wl-+f2Pa;2hX~Tt!7d6plPo6wU$0_cQZB57?K44lITyU3&1mNNQ%_8es z=4U5>2dU;4E_9vC|H+I?Jxxz%VU$S2-w-0ZM6(*M2M-_qjfAA8?jIi?#}hsK{r8)# ztvbHkGOF6i=CTYj^LuX{x_N!DLCC60?&tJ~T9Cl`KN1r99;!)4r=~u__ZH{-Wtf1Q#w{%d!8L=GHir5FsVrvpntfPbsK;r z0JkE_%N6r{9e;d(hYZ-^GW9}F=wbtP@yDBdA^o?@a&!fe(w1#mkHJ}RZC*F8Oc_x}Cf=PwcpMXh@j+wHs8i(YOm zS92L>f>x20m0kJb?5i$>p%dMY+|R50-4@iz!Ql)y^jCkNChEb$!Xj1i_;FrAK|e$l z>>ByShZi72A6Tf({&;%OPfPHg-in}!cRQj+$I7^wxVThJO}DE*Q#Js3wwL76$_8s7 zY|@)mun!;FwrL%1Sb%O`Hr1$C6F)iB64Wu@Csr9H6BV`a-AqniUdXa(Z=~b5U7(_J zTQ__e8~`aa`J8M*)yeRmpLcG*F?}9%O;J%%e{!I<)xP`wae(+>8CU6vzAB^H z@m{p{4NOeG)Drk9cIk<`kVjmk<2_bA=YTiuj^2;=oZHCASm4kfQTF|F3Om{(KbQTN zGuu!4}Y$`E0p(hpA*7`U9i z3ngTI+b!4gQS?eXDMiI&$0!IDQcU$xVBk?i^G%yA2XG{3X>pDy2o@by6+QN!qe+}{ zay^4r#=1)A*!SHbpYMfOBdTZcb$(>J|H9xI4d_*|QWC7M*p6KN|0W?J;pOG5uIcPfDBQJy4FF!G=Q_VKS=x$ZHX*}Rum$?jHi?pjYVMXp(6rxN zehOfOE&;?s&KaAT)yJ#vK-yKZ=N$nsHG#rOQh0eK0!%akGRsQ{Gzx-QI33!@bC zmKH{Apb%@5j1)kM51%>1j1B6e<{g=unrbpMG!zdZiU2RfuY-mVb#h8wJ;_0mi-w+4 zQCXP|q+WY3n{oX!mG2$-QE((JqcZx?&`|NE`3bTc6iUY? zkJkXHg0tt(SG_|AHJEVB6=&w=u7OmJfBrlsZKC?1A2gHYNdA&Ex)ovNt=1L%r0B&u zoFAUpdFK)sK6y#%e=XDY6FNGTMBBK#yBoBi1B1#u0Z%5>0{v1LP)lNkZPZ9HUC$4c z_A${U_~gSW@!(QRy4Ck4Avw9cU37ZUkcCDqAWPt_&H-vN3!Ajjo338K1EH)Ep-0hX zjzH}|bH-(6vTNJe2xr@k^u>4!P>{$VVBn=B0b^rVwZtktEU&KKPNfn7SXW=aOHeQ_ zjZ4ZAMAh3w(-}M&_~_l!V+_}d4Uy@Oa+Qugu_mmnyYn`!z*fjWf%91#*x8kkVI*oS zdeOkT19rp8Cr>iIIQQBVv>!lDxN}vQm<_fV9?iS=?+fGq_+ux?J=n~8$U(w2&}+fu z*wHWXVEaWx#vpdBW4?X6Ul@1!fNJo=&=G?gyY&r;Gkt=2Q?t8%9 zx)d`tA}Ud%P4J|U!DXTrb=#nsBu?V-$kQOkXd5ey=*YGMa#BrwqSK&p-a#s1ciz$I z3BhI)Y1An~#;Muci(~1KAB^nm?|x&|dF#cEWvFeFR= z+gmGeNPHsPoUSan7R!t6Q(ttALQzfB0|+(SUYD+A`76Ad`BH z9jCsPz#ln|B7`ZTUlGWU9{K_F0zp|%%`+v1eiF{(IlUVqF!6}mM#(}p#PK5ath!5+ zt`DAtI#jrHiNBO>l8a*l?s$3<7;>B*uDbX- z*TY0J+;wr5xC^B8&b&A)bm8Mp)sMMOcA$(7b3<>?jbooZ+lLy%diejNdsaWYeS5_| zVPT0D$Zq1`5I@AGN(4w81n$07SomSeuDQk+i8C~Wgcz0j@a)>P7S8GgP3Iz95H+DE z^P_RH)~#BB7r%Omv-G@+%&%TDw*V|6?-dsppMdR#0N*;ajFC~| z4Za1C|Jcv~VlAtkXuc8v7aJRU0;C>-@Xrs~q5WV#{_JDsv@DmlA*dM{;^<==7z3_w z|4)|q&sx?$*x9x8XfEKGsJ`&^@B%)5JWZ`QA{U#RXzq!(fz+Un)}qMClQ26S9S=|_ zL+;UA@UZZls##t)9^bm*kX)>k&|l{Gk;S1U=Tq-(E=rrZI;@X-5WrS4#Ot*8`IU8g z?x^~sK5PXrxXa(a?|N~q`@YydmwEfk8J#qyRiW~z31TB}2>4Net7M8qrR3*$2$Em@ z4bIhnrQ3o?(BxfR6^wMTX)bQi8v$L=@9)d}}Bg7i!u@K0)3ruAS zrLJ)6QaUbFpO&9P6Zdy32_AMiipUMN{dL4gC2m1HRXg1W+A-O7 zNbA?8@>6@lf5HXN=nd4)7>MysEGaD=Pl;Oafm7fk)PyGF@GU+L#^p+s>g3mYPfspK zFGAr?!<|)ElPZBS{sWB$hAmZ#f4gnB(DMMlI;ll7XdqT`2I}28G7h^?*_({8X4k@{I?OO2ParC8ns1B`7 ztgHk=wT>$)ZUrl-ky#2y+y4-gkrAvKaiBKS#*9c|;ESm*SdL~Ze1CTQ~~iHZLDd&`NVq9WFI2Sgo(aBZ;RK9OO( z3cf@xP7FNp!n1oz``^F<;a)bdj($dnDBMv-1wDnL; zq*REo89mSz5T*4m{*9r93~P!QWGcY~WRZL_v+vZ%P%cR&c<(Kx;kWGHocnF67C`zAY$BvN-kRiVb}nwMr{9}#>bYvF>cjfpb=6>>qIuiNyQ;vf${6c^SF$*w|`uZVy zWygNV2+8@;BFpxi5S1`d15Fmn_>dV-|3{Q-2C*T4`+%RFP(iTe#tUf$6EO(_tGo#= z97cd=zKbXK~gRfhvW%HwaErWr2myviFFW`N~V060?~0v z24~vzpVHA$?#R0_+cx6jX`(4P+w+i9#w8qvOCmJq?%lh|q|2`DI;&ps$h0t$kJxE> z&JvV57q*`8UHtqeAa6v%uo;`JU4Bu6e zOgw(rOPKQAL|N=}U34a^?yCwbBbAF;vLfmo)*R6^XuZUQ!Ai;Jq?hJx^2&cd>^AT@ zWe25hk*s0&?!pF;HdPZ0r-?4Y2+$KU0R%h~Lk%$4xajCx!pv({k+D|d)KCj+%O5A7 zU@(N~IPwh87b_3yfjL|WnKXbgea4nkD6iOi!ePWW5ry{{IvV`a>;CP z94riuC2wrJE#1p&jpf+bSSs}Y{{8zuP$VQm8bI^R&CS7HMBKuKzkdDNWINJc#R`+r zIRwl!PkHC27!eqL#D(0^ZJoJ+adsb#gc)?|*OoVe4h{~OnrcnVEfAv)8s`_Za!DP7 zJA+agkS3A;}e?(L1$=W^f~MLo^)Ik0V&HorK$N2mSB$Z-X)%ESg>(arg zaU@z08Hx&yzg@{d;EY93R~hlgM7HnoIo(d3U?C$KH1xQV>AYzvOFzl+HBS`$j>_fb z{s#kZe)u;A9!4xef)TM&<%?6h|0_(Gdjb|Pj0oq)FOf9TJm@g9y#dT7)vAeX?VOL?*6_KL@eaJS8wPIW!em`dw&&CD=J| z4aRlu8v?F~(Ms?~Z{U3X$I~o8HgD%d*!a@!^1f92Khne)tpHI|ZF4lT=CE-I*+Vr+V%_XoH$UJf+cbbb; z=j!ro+o71OtWY>i4lt zYQb-0kV%UH7ZP{7kPu_b^D{3n#Up}NIb1vdkt5X+vaj@nx;hc#gcT!NhArureu>`^ zr;cCFDYy}MhCb$en>KCo4-I{fMcE_|h+Jb~@n{^BCoQjVta+KI z@27G3BRo3~ob}F^zDdg(!IUHC)GB`R%o%rnO!L%t?b-7rCgwId4`7=;=9o(idu%$` zr-V9kj_BJaAWG8pk@hV{bU1kddTKR4W2FVb=pPVpi(gcfh%A7L-ZM~BGQwTHl1Bem z6EijM4-J)lbh_c>8P?wiH28TIWuiB1LMG~QFVl(Tv%mWz!|FX5WM019cN&%onkw<$ zi%Ux}d?E)TlwnTb%ukYLpnKKeR9zvPEUZC(_@J*e1Hu1#P9xH<^A`_99Jn6iy0qw3 z{w69qf>v0dt}FMZ_qVKN@(LH%x^LZd+fCu(XyfXuofIja2j+fZOLFjV(g6wM@{snk z```sRw~>(>*mA(*$0e{bh{D^7Kwa~lULi0)wVa;oRp*!5%@;P`zUiI1N>JLb#1)5PoeV`auWilUeU_QulPh4x_CQEsm@=p%E-m#OQ>3{Dw2wqLaF}urV+3k5L-SzKKSg_G;dl| zU@8Tg@KEY>HBx2q_O|WYyQUl^IG|F%j(DV`wg8n2KhXcSVmT&hX5Nj1d>htmrPM|K zgSX*-B^+cPrs!vws<3pJX(f20H%Ly7i_%Oh8Y(ZTiYH;87srG06S1|Rl}g8s8A7>3 zoz}rT%ZrCRDq6`P`Bu0_vIrg;013Ey375#Q=eTl7(4flql*i;TifCO`2>kWcZ#rBK z-uOA$S*yU!2YrYhPtGC{-F*8uTHum%{l||VNk7HG5K5i2M!AK>1$v!qDQ7K+m9!Eg*eF_M3B3q6v-bJOxVj_&;5rnOB`jrk}9ODCF?OB`~ zAf8__^7%$Kbj&)Zq;##tt+tOuO|d<4{#zQ5q7kDOh3uFl2H z5uR&>1x(vNMs@b{**rUT{P<@`@i(p3w54oX6SK~e3zPMe!);-(R52q(!fvr&m};Eu zmswK6kdiP6v-inVUrvc5@QrC%sQScW!0->g;$zIR#~>spKwch1Mft%8CbAWWL1)g7eK-qhOI!}SR;$&7{oWB<$`1Z2c!_sYm+M+l&x{dn?y=znUX9X{%CMip z^Et-hJOBSMQ@vQs&da!*e8}h@K)#hS5Hfhmg^WTFZ5xvjdbR<6D5jk zmKGT~?6`R3elHF7$r1xLd4h>ADa%)v3c4>xZhOxPMHUwkThyRO0i z9t+B!cVEqAzl_nsm3jwTFFa97o9WtF*5hh>$7wN-`3R5bki@ZItFalC1@=1OyGz8B zxiR;HjEoE1R>NW8M~}f^xDzw~7@PiTPASJnFu_4^lbBgpz`t;~5k`0|AZvv-X4L#h zEeTe%bx&9<-#*5t!b|JID)@*2Mg9coHQ`wjoj!L$KM%OwF zB+y%)k&c5+A$$)UdHP@DijHxCu^fKvv8p3uQY`TBDn(#}-R zAF&wwRaPpi_O+c?NL)V@QT%oHFGu_@n_;!&a41Vj zX)VrEq!bL$~Q*Y9l$?M8Q-LZ@#Dv~LVICemZ8}C08)hSd(H^lA-!8SjWZNVuuY*t#Q)|4@~ zruP%MLDTye9OTu~)VS#Lix)y1HFp4{194)q*E+ySbN7gg?z@i05rZq5{LE>~@uXdp swrgs>#>OKW9>yhI)|ppvVHq09jge}G^xpXYMwThbtI8!D(ZBtF05;BqO#lD@ literal 0 HcmV?d00001 diff --git a/e2e/testcafe-devextreme/tests/cardView/etalons/headers.png b/e2e/testcafe-devextreme/tests/cardView/etalons/headers.png new file mode 100644 index 0000000000000000000000000000000000000000..f867d818c52a29ece6a5f9c52f47255fc06590e9 GIT binary patch literal 2367 zcmV-F3BdM=P)wBRkA78HSM^=9mn_$c|ap5x;-`c3-}HabLfFbw7Uma6f63|SOj*8sxm&er zl^5A4FwOLruC$cwm=M(a_wU_@4Dt z39SEgX=l^SWRq(D#*T^c0c(m+4(fWf8JsrF7?7f+#*T?WOB2{+fxWSNDyA7j#A>OL zVpf#s;wyA=_$(vZj`o<6gabwbk**jXr9r)-myyffR1s zxZw^QIN**PIpPi;Jm@P8C)EYyGY-*V5L`GHE?jU^Q&Zkh{AOJW?0@|D@yh+#Mw--% zRev36N~&hKsL%|0N!1MJc;(8K&Vu2-ef$1?&@#4)Ez{%2kB8Lf{$Mo&nHx~;6 zyL9Q2JA3x5yMO<_cT(H8Z}&p$!a#TK+;NvLUv}dN<>taUcI=oJI~O9qSx244!e0Q$ zgZ;|{#X7c;hP0{hf3~KiYKDu7y5KjOp}bvbrVW(q`t|GX{Q2{KIo4s4ei(tY&sv)K z=MPm07%TYo>z9iGhosgLa1uLr?sV6#U2~f^Z+1I&?C|1a{fZSUd>Rb>XqM*Nm@9%hYugR=g*(}{k6WBo?{3^L3-BX)Sf+i=GLxV>$eTs z2Z(f}XIofS%D^$%M!v=Us-WzL4juA!^Web)zYgJY9&g{ib$j;gak1>)z1x2y93p49 zEa4L6+CaWK|2k4MbMfLuf9@wwp7eD~eed7Df8IGsBh(XhPrZ{?cEYYKqpib-56{yU z+p+VeO`HC%FX}@1g>ZcA#kO_p)_Dg&8SdV_>oqP^2Da%K92Xm-7naEzJ6Dw{hCXYl zcCL8r9T}nomQ(qm*9g!DvPrRTU9 zjfjW1w4G&Oe>MO4M$kYsLQs46?)3r=^J5zm=BeCWyLQbJXdRTZ4DyJ{r-;NtIYn1O zf*2j7XofmIb?Vgrw$Y_iYXgnY5YH-1o#O-RrCZJi9jHvC*K!Pf)>5rwik)DmW;Y@!BJW#=oDU8Ja265* z#*l+z9mu<@`AP+nj{W%!I4x}_KMco(pjI7DMv<1h5iI-bJT$N<$Hlqm__H?XE~;8q82i(boS#LZK+JuIjte| zg-)a!>7TN)EZc-#q+D2NEsf?m7m;9i1fErqqaff^ ziXv|c`5~O#x@uJn8l3D(P%)3LNYM;hp`}`EiQc<+Z(tWfTEq5bw${3^8`TB0bjXim zqcc8Xx4&vG(Xh(YB{^uR)^#mfw8+K6$(dO2zTYuA&FJeiJLK;xlEmM_0EMra#5)!|4`#5!Oi-^%die^+!UDT@c@Xk;f z*ot$L?L()4qhMe1(ROqZJJp21$o_oTm!PYlr2re|Up6&BdL?~XnHaXnfn2my>$;XM zUF!SjF%S(TEGitMV2p5_h;e~)=gxT{AwF6u049K#a8h6TYd>Thm`V%Kk zc*AqNqeqV>J0=8;@F>6T-r-0!@SPK!D|I+%a8m0u0GryyMF%lyV>N>fsdG&j1Zk$K zdqe=^9MOvA;e?PUc}Pptm*yiiMdcx|qSJ8j9bM>Vi^|M84F`a3-e{1%tW0OloN)_H zPFkvcP#j|gFJ8Pze*6Va1%nPciK^`yNG#i~ZN(;h-SN6Ee;b&)L-n`qGBz1BZ9A~K zb?er~<4nWWOv*lk^wJe|`InWi%QE#%OO2jj$z(12zgzdH+mYMAXOU&gmbvxo*GKJR zni(y9(^4bH#Dpj!pfQa#QZ<;ZR#AvDU zdi745cg&e)43L&$h*F(i z#bQG1H(lD) => class ColumnC export const columnChooserModule = { defaultOptions() { - return { - columnChooser: { - enabled: false, - search: { - enabled: false, - timeout: 500, - editorOptions: {}, - }, - selection: { - allowSelectAll: false, - selectByClick: false, - recursive: false, - }, - position: undefined, - mode: 'dragAndDrop', - width: 250, - height: 260, - title: messageLocalization.format('dxDataGrid-columnChooserTitle'), - emptyPanelText: messageLocalization.format('dxDataGrid-columnChooserEmptyText'), - // TODO private option - container: undefined, - }, - }; + return defaultOptions; }, controllers: { columnChooser: ColumnChooserController, diff --git a/packages/devextreme/js/__internal/grids/new/card_view/main_view.tsx b/packages/devextreme/js/__internal/grids/new/card_view/main_view.tsx index 05dad093833c..8d8e122f05d4 100644 --- a/packages/devextreme/js/__internal/grids/new/card_view/main_view.tsx +++ b/packages/devextreme/js/__internal/grids/new/card_view/main_view.tsx @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { combined } from '@ts/core/reactive/index'; +import { ColumnChooserView } from '@ts/grids/new/grid_core/column_chooser/index'; import { View } from '@ts/grids/new/grid_core/core/view'; import { FilterPanelView } from '@ts/grids/new/grid_core/filtering/filter_panel/view'; import { HeaderFilterPopupView } from '@ts/grids/new/grid_core/filtering/header_filter/index'; @@ -25,12 +26,14 @@ interface MainViewProps { HeaderPanel: ComponentType; HeaderFilterPopup: ComponentType; FilterPanel: ComponentType; + ColumnChooser: ComponentType; config: Config; rootElementRef: RefObject; } function MainViewComponent({ - Toolbar, Content, Pager, HeaderPanel, HeaderFilterPopup, FilterPanel, config, rootElementRef, + Toolbar, Content, Pager, HeaderPanel, HeaderFilterPopup, + FilterPanel, ColumnChooser, config, rootElementRef, }: MainViewProps): JSX.Element { return (<> @@ -53,6 +56,7 @@ function MainViewComponent({ */} + ); @@ -68,6 +72,7 @@ export class MainView extends View { HeaderPanelView, HeaderFilterPopupView, FilterPanelView, + ColumnChooserView, OptionsController, ] as const; @@ -78,6 +83,7 @@ export class MainView extends View { private readonly headerPanel: HeaderPanelView, private readonly headerFilterPopup: HeaderFilterPopupView, private readonly filterPanel: FilterPanelView, + private readonly columnsChooser: ColumnChooserView, private readonly options: OptionsController, ) { super(); @@ -93,6 +99,7 @@ export class MainView extends View { HeaderPanel: this.headerPanel.asInferno(), HeaderFilterPopup: this.headerFilterPopup.asInferno(), FilterPanel: this.filterPanel.asInferno(), + ColumnChooser: this.columnsChooser.asInferno(), config: combined({ rtlEnabled: this.options.oneWay('rtlEnabled'), disabled: this.options.oneWay('disabled'), diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/column_chooser.tsx b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/column_chooser.tsx new file mode 100644 index 000000000000..df3a43f3011f --- /dev/null +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/column_chooser.tsx @@ -0,0 +1,46 @@ +import type { ColumnChooserMode } from '@js/common/grids'; +import type { Properties as PopupProperties } from '@js/ui/popup'; +import type dxPopup from '@js/ui/popup'; +import type { Properties as TreeViewProperties } from '@js/ui/tree_view'; +import type dxTreeView from '@js/ui/tree_view'; +import type { RefObject } from 'inferno'; + +import { Popup } from '../inferno_wrappers/popup'; +import { TreeView } from '../inferno_wrappers/tree_view'; + +export interface ColumnChooserProps { + popupRef: RefObject; + + treeViewRef: RefObject; + + visible: boolean; + + mode: ColumnChooserMode; + + popupConfig: PopupProperties; + + treeViewConfig: TreeViewProperties; +} + +export function ColumnChooser(props: ColumnChooserProps): JSX.Element | null { + const { + visible, treeViewConfig, popupConfig, popupRef, treeViewRef, + } = props; + + if (!visible) { + return null; + } + + return ( + + + + ); +} diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts new file mode 100644 index 000000000000..f40b1a32a918 --- /dev/null +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts @@ -0,0 +1,192 @@ +/* eslint-disable spellcheck/spell-checker */ +import { describe, expect, it } from '@jest/globals'; +import type { SelectionChangedEvent } from '@js/ui/tree_view'; + +import { ColumnsController } from '../columns_controller'; +import type { Options } from '../options'; +import { OptionsControllerMock } from '../options_controller/options_controller.mock'; +import { ColumnChooserController } from './controller'; +import { expectColumnVisibility } from './test-utils.test'; + +const createColumnChooserController = (options?: Options): { + controller: ColumnChooserController; + columnsController: ColumnsController; + optionsController: OptionsControllerMock; +} => { + const optionsController = new OptionsControllerMock(options ?? { + columnChooser: { + enabled: true, + }, + }); + const columnsController = new ColumnsController(optionsController); + + const columnChooserController = new ColumnChooserController(columnsController, optionsController); + + return { + controller: columnChooserController, + columnsController, + optionsController, + }; +}; + +describe('ColumnChooser', () => { + describe('Controller', () => { + describe('chooserColumns state', () => { + const expectChooserColumns = ( + controller: ColumnChooserController, + columnNames: string[], + ): void => { + const columns = controller.chooserColumns + .unreactive_get() + .map((column) => column.name); + + expect(columns).toEqual(columnNames); + }; + + it('is correct', () => { + const { controller } = createColumnChooserController({ + columns: [ + { dataField: 'A Column' }, + { dataField: 'B Column' }, + ], + }); + + expectChooserColumns(controller, ['A Column', 'B Column']); + }); + + it('is correct when a column has showInColumnChooser=false', () => { + const { controller } = createColumnChooserController({ + columns: [ + { dataField: 'A Column' }, + { dataField: 'B Column', showInColumnChooser: false }, + { dataField: 'C Column' }, + ], + }); + + expectChooserColumns(controller, ['A Column', 'C Column']); + }); + + it('is correct when sortOrder is set', () => { + const { controller, optionsController } = createColumnChooserController({ + columns: [ + { dataField: 'C Column' }, + { dataField: 'A Column' }, + { dataField: 'B Column' }, + ], + columnChooser: { + sortOrder: 'asc', + }, + }); + + expectChooserColumns(controller, ['A Column', 'B Column', 'C Column']); + + optionsController.option('columnChooser.sortOrder', 'desc'); + + expectChooserColumns(controller, ['C Column', 'B Column', 'A Column']); + }); + }); + + describe('items state', () => { + it('is correct', () => { + const { controller } = createColumnChooserController({ + columns: [ + { dataField: 'A Column' }, + { dataField: 'B Column', caption: 'B Caption' }, + ], + }); + + expect(controller.items.unreactive_get()).toEqual( + [ + { + id: 0, columnName: 'A Column', selected: true, text: 'A Column', disabled: false, + }, + { + id: 1, columnName: 'B Column', selected: true, text: 'B Caption', disabled: false, + }, + ], + ); + }); + + it('updated when column option changed on select mode', () => { + const { columnsController, controller } = createColumnChooserController({ + columns: ['Column 1', 'Column 2', 'Column 3', 'Column 4', 'Column 5'], + columnChooser: { + enabled: true, + mode: 'select', + }, + }); + + const getItems = () => controller.items.unreactive_get(); + const getItem = (index: number) => getItems()[index]; + + const columnOption = (index: number, option, value) => { + const column = columnsController.columns.unreactive_get()[index]; + columnsController.columnOption(column, option, value); + }; + + columnOption(0, 'showInColumnChooser', false); + expect(getItems().filter((item) => item.columnName === 'Column 1')).toHaveLength(0); + + columnOption(0, 'showInColumnChooser', true); + expect(getItem(0).columnName).toBe('Column 1'); + + // test column.visible + columnOption(1, 'visible', false); + expect(getItem(1).selected).toBeFalsy(); + + columnOption(1, 'visible', true); + expect(getItem(1).selected).toBeTruthy(); + + // test column.caption + columnOption(2, 'caption', 'new caption'); + expect(getItem(2).text).toBe('new caption'); + + // test column.name + columnOption(3, 'name', 'new name'); + expect(getItem(3).columnName).toBe('new name'); + + // test column.allowHiding + columnOption(4, 'allowHiding', false); + expect(getItem(4).disabled).toBeTruthy(); + + columnOption(4, 'allowHiding', true); + expect(getItem(4).disabled).toBeFalsy(); + }); + }); + + it('onSelectionChanged', () => { + const { controller, columnsController } = createColumnChooserController({ + columns: [ + { dataField: 'A Column' }, + { dataField: 'B Column' }, + { dataField: 'C Column', allowHiding: false }, + { dataField: 'D Column', allowHiding: false }, + { dataField: 'E Column', visible: false }, + { dataField: 'F Column', visible: false }, + { dataField: 'G Column', allowHiding: false, visible: false }, + { dataField: 'H Column', allowHiding: false, visible: false }, + ], + }); + + controller.onSelectionChanged({ + component: { + getNodes: () => [ + { itemData: { columnName: 'A Column' }, selected: true }, + { itemData: { columnName: 'B Column' }, selected: false }, + { itemData: { columnName: 'C Column' }, selected: true }, + { itemData: { columnName: 'D Column' }, selected: false }, + { itemData: { columnName: 'E Column' }, selected: true }, + { itemData: { columnName: 'F Column' }, selected: false }, + { itemData: { columnName: 'G Column' }, selected: true }, + { itemData: { columnName: 'H Column' }, selected: false }, + ], + }, + } as unknown as SelectionChangedEvent); + + expectColumnVisibility( + columnsController, + [true, false, true, true, true, false, true, false], + ); + }); + }); +}); diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.ts new file mode 100644 index 000000000000..c29829ce15cd --- /dev/null +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.ts @@ -0,0 +1,65 @@ +import type { Item as TreeViewItemProperties, SelectionChangedEvent } from '@js/ui/tree_view'; +import type { SubsGets } from '@ts/core/reactive/index'; +import { computed } from '@ts/core/reactive/index'; +import { sortColumns } from '@ts/grids/grid_core/columns_controller/m_columns_controller_utils'; + +import { ColumnsController } from '../columns_controller/columns_controller'; +import type { Column } from '../columns_controller/types'; +import { getColumnIndexByName } from '../columns_controller/utils'; +import { OptionsController } from '../options_controller/options_controller'; + +export class ColumnChooserController { + public static dependencies = [ColumnsController, OptionsController] as const; + + public readonly chooserColumns: SubsGets; + + public readonly items: SubsGets; + + constructor( + private readonly columnsController: ColumnsController, + private readonly options: OptionsController, + ) { + this.chooserColumns = computed( + (columns, sortOrder) => { + let chooserColumns = columns.filter((column) => column.showInColumnChooser); + chooserColumns = sortColumns(chooserColumns, sortOrder); + + return chooserColumns; + }, + [ + this.columnsController.columns, + this.options.oneWay('columnChooser.sortOrder'), + ], + ); + + this.items = computed( + (chooserColumns) => chooserColumns.map((column, index) => ({ + id: index, + columnName: column.name, + selected: column.visible, + text: column.caption, + disabled: !column.allowHiding, + }) as TreeViewItemProperties), + [this.chooserColumns], + ); + } + + public onSelectionChanged(e: SelectionChangedEvent): void { + const nodes = e.component.getNodes(); + + this.columnsController.updateColumns((columns) => { + for (const node of nodes) { + const columnIndex = getColumnIndexByName(columns, node.itemData?.columnName); + const canHide = columns[columnIndex].allowHiding ?? true; + // in case when allowHiding=false and node.selected=false, we do not hide column + const skip = !canHide && !node.selected; + + if (!skip) { + columns[columnIndex].visible = node.selected; + } + } + + return [...columns]; + }); + } +} diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/index.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/index.ts new file mode 100644 index 000000000000..6e100f85fc05 --- /dev/null +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/index.ts @@ -0,0 +1,4 @@ +export { ColumnChooserController } from './controller'; +export { defaultOptions, type Options } from './options'; +export { PublicMethods } from './public_methods'; +export { ColumnChooserView } from './view'; diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/options.integration.test.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/options.integration.test.ts new file mode 100644 index 000000000000..7f4e1262bee4 --- /dev/null +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/options.integration.test.ts @@ -0,0 +1,304 @@ +import { + afterEach, describe, expect, it, +} from '@jest/globals'; +import type { PositionConfig } from '@js/common/core/animation'; +import $ from '@js/core/renderer'; +import type dxPopup from '@js/ui/popup'; +import type dxTreeView from '@js/ui/tree_view'; +import CardView from '@ts/grids/new/card_view/widget'; +import type { Options as GridCoreOptions } from '@ts/grids/new/grid_core/options'; +// eslint-disable-next-line spellcheck/spell-checker +import { rerender } from 'inferno'; + +import { CLASSES as ContentViewClasses } from '../content_view/content_view'; +import { defaultOptions } from './options'; + +const SELECTORS = { + cardView: '.dx-cardview', + columnChooserBtn: '.dx-cardview-column-chooser-button', + popup: '.dx-popup', + treeView: '.dx-treeview', +}; + +const rootQuerySelector = (selector: string) => document.body.querySelector(selector); + +const setup = (options: GridCoreOptions = {}): CardView => { + const container = document.createElement('div'); + const { body } = document; + body.append(container); + + return new CardView(container, options); +}; + +const setupOpened = (options: GridCoreOptions = {}) => { + const cardView = setup(options); + + cardView.showColumnChooser(); + // eslint-disable-next-line spellcheck/spell-checker + rerender(); + + return cardView; +}; + +const getPopupInstance = (): dxPopup => { + const popupElement = rootQuerySelector(SELECTORS.popup); + const instance = ($(popupElement ?? undefined) as any).dxPopup('instance') as dxPopup; + + return instance; +}; + +const getTreeViewInstance = (): dxTreeView => { + const treeViewElement = rootQuerySelector(SELECTORS.treeView); + const instance = ($(treeViewElement ?? undefined) as any).dxTreeView('instance') as dxTreeView; + + return instance; +}; + +describe('Options', () => { + afterEach(() => { + const cardView = rootQuerySelector(SELECTORS.cardView); + // @ts-expect-error bad typed renderer + $(cardView ?? undefined as any)?.dxCardView('dispose'); + }); + + describe('ColumnChooser', () => { + it.each([ + { value: true, result: true }, + { value: false, result: false }, + { value: undefined, result: false }, + ])('enabled: %s', ({ value, result }) => { + setup({ columnChooser: { enabled: value } }); + + const button = rootQuerySelector(SELECTORS.columnChooserBtn); + + expect(!!button).toBe(result); + }); + + it.each<{ + value?: number; result: number | string | undefined; + }>([ + { value: undefined, result: defaultOptions.columnChooser?.width }, + { value: 100, result: 100 }, + { value: 1000, result: 1000 }, + ])('width: $value', ({ value, result }) => { + const cardView = setup({ + columnChooser: { enabled: true, width: value }, + }); + cardView.showColumnChooser(); + + const popup = getPopupInstance(); + + expect(popup.option('width')).toBe(result); + }); + + it.each<{ + value?: number; result: number | string | undefined; + }>([ + { value: undefined, result: defaultOptions.columnChooser?.height }, + { value: 100, result: 100 }, + { value: 1000, result: 1000 }, + ])('height: $value', ({ value, result }) => { + const cardView = setup({ + columnChooser: { enabled: true, height: value }, + }); + cardView.showColumnChooser(); + + const popup = getPopupInstance(); + + expect(popup.option('height')).toBe(result); + }); + + it.each<{ + value?: string; result?: string; + }>([ + { value: undefined, result: undefined }, + { value: '#custom', result: '#custom' }, + ])('container: $value', ({ value, result }) => { + setupOpened({ + columnChooser: { enabled: true, container: value }, + }); + + const popup = getPopupInstance(); + + expect(popup.option('container')).toBe(result); + }); + + it.each<{ + value?: PositionConfig; result: PositionConfig; + }>([ + { + value: undefined, + result: { + my: 'right bottom', + at: 'right bottom', + of: ContentViewClasses.contentView, + collision: 'fit', + offset: '-2 -2', + boundaryOffset: '2 2', + }, + }, + { + value: { + my: 'right top', + at: 'right bottom', + of: '.dx-cardview-column-chooser-button', + }, + result: { + my: 'right top', + at: 'right bottom', + of: '.dx-cardview-column-chooser-button', + }, + }, + ])('position: $value', ({ value, result }) => { + setupOpened({ + columnChooser: { enabled: true, position: value }, + }); + + const popup = getPopupInstance(); + + expect(popup.option('position')).toMatchObject(result); + }); + + // Implement when dragAndDrop mode is developed + it.skip.each<{ + value?: string; result?: string; + }>([ + { value: undefined, result: defaultOptions.columnChooser?.emptyPanelText }, + { value: 'custom value', result: 'custom value' }, + ])('emptyPanelText: $value', ({ value }) => { + setupOpened({ + columnChooser: { enabled: true, emptyPanelText: value }, + }); + + // TODO + }); + + it.each<{ + value?: string; result?: string; + }>([ + { value: undefined, result: defaultOptions.columnChooser?.title }, + { value: 'custom value', result: 'custom value' }, + ])('title: $value', ({ value, result }) => { + setupOpened({ + columnChooser: { enabled: true, title: value }, + }); + + const popup = getPopupInstance(); + + expect(popup.option('toolbarItems[0].text')).toBe(result); + }); + + it.each<{ + value?: boolean; result: boolean; + }>([ + { value: undefined, result: false }, + { value: true, result: true }, + { value: false, result: false }, + ])('search.enabled: $value', ({ value, result }) => { + setupOpened({ + columnChooser: { enabled: true, search: { enabled: value } }, + }); + + const treeView = getTreeViewInstance(); + + expect(treeView.option('searchEnabled')).toBe(result); + }); + + it.each<{ + value?: number; result: number; + }>([ + { value: undefined, result: 500 }, + { value: 100, result: 100 }, + { value: 1000, result: 1000 }, + ])('search.timeout: $value', ({ value, result }) => { + setupOpened({ + columnChooser: { enabled: true, search: { enabled: true, timeout: value } }, + }); + + const treeView = getTreeViewInstance(); + + expect(treeView.option('searchTimeout')).toBe(result); + }); + + it.each<{ + value?: Record; result: Record; + }>([ + { result: {} }, + { value: { disabled: true }, result: { disabled: true } }, + { value: { height: 999 }, result: { height: 999 } }, + ])('search.editorOptions: $value', ({ value, result }) => { + setupOpened({ + columnChooser: { enabled: true, search: { enabled: true, editorOptions: value } }, + }); + + const treeView = getTreeViewInstance(); + + expect(treeView.option('searchEditorOptions')).toMatchObject(result); + }); + + // Implement when dragAndDrop mode is developed + it.skip.each<{ + value?: 'select' | 'dragAndDrop'; result?: 'select' | 'dragAndDrop'; + }>([ + { value: undefined, result: defaultOptions.columnChooser?.mode }, + { value: 'select', result: 'select' }, + { value: 'dragAndDrop', result: 'dragAndDrop' }, + ])('mode: $value', ({ value }) => { + setupOpened({ + columnChooser: { enabled: true, mode: value }, + }); + + // TODO + }); + + it.each<{ + value?: boolean; result: 'selectAll' | 'normal'; + }>([ + { value: undefined, result: 'normal' }, + { value: true, result: 'selectAll' }, + { value: false, result: 'normal' }, + ])('selection.allowSelectAll: $value', ({ value, result }) => { + setupOpened({ + columnChooser: { enabled: true, mode: 'select', selection: { allowSelectAll: value } }, + }); + + const treeView = getTreeViewInstance(); + + expect(treeView.option('showCheckBoxesMode')).toBe(result); + }); + + it.each<{ + value?: boolean; result: boolean; + }>([ + { value: undefined, result: false }, + { value: true, result: true }, + { value: false, result: false }, + ])('selection.selectByClick: $value', ({ value, result }) => { + setupOpened({ + columnChooser: { enabled: true, mode: 'select', selection: { selectByClick: value } }, + }); + + const treeView = getTreeViewInstance(); + + expect(treeView.option('selectByClick')).toBe(result); + }); + + it.each<{ + value?: 'asc' | 'desc'; result: string[]; + }>([ + { value: undefined, result: ['B Column', 'C Column', 'A Column'] }, + { value: 'asc', result: ['A Column', 'B Column', 'C Column'] }, + { value: 'desc', result: ['C Column', 'B Column', 'A Column'] }, + ])('sortOrder: $value', ({ value, result }) => { + setupOpened({ + columns: ['B Column', 'C Column', 'A Column'], + columnChooser: { enabled: true, sortOrder: value, mode: 'select' }, + }); + + const treeView = getTreeViewInstance(); + const items = (treeView.option('items') ?? []).map((item) => item.text); + + expect(items).toEqual(result); + }); + }); +}); diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/options.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/options.ts new file mode 100644 index 000000000000..0d305be6bacd --- /dev/null +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/options.ts @@ -0,0 +1,12 @@ +import type { ColumnChooser, ColumnChooserSelectionConfig } from '@js/common/grids'; + +import { defaultOptions as columnChooserDefaultOptions } from '../../../grid_core/column_chooser/const'; + +export interface Options { + columnChooser?: Omit & { + // TODO: change d.ts files. Recursive selection isn't supported in CardView yet. + selection?: Omit; + }; +} + +export const defaultOptions = columnChooserDefaultOptions as Options; diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/public_methods.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/public_methods.ts new file mode 100644 index 000000000000..3b157859e9b4 --- /dev/null +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/public_methods.ts @@ -0,0 +1,18 @@ +/* eslint-disable spellcheck/spell-checker */ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ + +import type { Constructor } from '../types'; +import type { GridCoreNewBase } from '../widget'; + +export function PublicMethods>(GridCore: TBase) { + return class GridCoreWithColumnChooser extends GridCore { + public showColumnChooser(): void { + this.columnChooserView.show(); + } + + public hideColumnChooser(): void { + this.columnChooserView.hide(); + } + }; +} diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/test-utils.test.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/test-utils.test.ts new file mode 100644 index 000000000000..20aa2a391e09 --- /dev/null +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/test-utils.test.ts @@ -0,0 +1,128 @@ +/* eslint-disable spellcheck/spell-checker */ +import { expect } from '@jest/globals'; + +import { ColumnsController } from '../columns_controller'; +import type { Options } from '../options'; +import { OptionsControllerMock } from '../options_controller/options_controller.mock'; +import { ToolbarController } from '../toolbar/controller'; +import { ToolbarView } from '../toolbar/view'; +import { ColumnChooserController } from './controller'; +import { ColumnChooserView } from './view'; + +const createToolbarView = (optionsController: OptionsControllerMock) => { + const toolbarElement = document.createElement('div'); + const toolbarController = new ToolbarController(optionsController); + const toolbar = new ToolbarView(toolbarController, optionsController); + + return { toolbarElement, toolbar, toolbarController }; +}; + +const createColumnChooserView = ( + optionsController: OptionsControllerMock, + toolbarController?: ToolbarController, +): { + columnChooserElement: HTMLDivElement; + columnChooser: ColumnChooserView; + columnChooserController: ColumnChooserController; + columnsController: ColumnsController; +} => { + const columnChooserElement = document.createElement('div'); + + const columnsController = new ColumnsController(optionsController); + const columnChooserController = new ColumnChooserController(columnsController, optionsController); + + const columnChooser = new ColumnChooserView( + toolbarController ?? new ToolbarController(optionsController), + columnChooserController, + optionsController, + ); + + return { + columnChooserElement, + columnChooser, + columnChooserController, + columnsController, + }; +}; + +export const renderColumnChooser = async (options?: Options): Promise<{ + element: HTMLDivElement; + optionsController: OptionsControllerMock; + columnChooser: ColumnChooserView; + columnChooserController: ColumnChooserController; + columnsController: ColumnsController; +}> => { + const optionsController = new OptionsControllerMock(options ?? {}); + const { + columnChooserElement, columnChooser, columnChooserController, columnsController, + } = createColumnChooserView(optionsController); + + columnChooser.render(columnChooserElement); + + columnChooser.show(); + + await new Promise((resolve) => { setTimeout(resolve); }); + + // we need to fire 'onShown' event manually, so that setPopupAttributes() is called + // @ts-expect-error + columnChooser.popupRef.current?.option('onShown')({ + component: columnChooser.popupRef.current, + }); + + return { + element: columnChooserElement, + optionsController, + columnChooser, + columnChooserController, + columnsController, + }; +}; + +export const renderColumnChooserWithToolbar = (options?: Options): { + element: HTMLDivElement; + toolbar: ToolbarView; + toolbarController: ToolbarController; + columnChooser: ColumnChooserView; + optionsController: OptionsControllerMock; + columnChooserController: ColumnChooserController; + columnsController: ColumnsController; +} => { + const optionsController = new OptionsControllerMock(options ?? {}); + const { + toolbarElement, + toolbar, + toolbarController, + } = createToolbarView(optionsController); + const { + columnChooserElement, + columnChooser, + columnChooserController, + columnsController, + } = createColumnChooserView(optionsController, toolbarController); + + const element = document.createElement('div'); + element.append(toolbarElement, columnChooserElement); + + toolbar.render(toolbarElement); + columnChooser.render(columnChooserElement); + + return { + element, + toolbar, + toolbarController, + columnChooser, + optionsController, + columnChooserController, + columnsController, + }; +}; + +export const expectColumnVisibility = ( + columnsController: ColumnsController, + visibility: boolean[], +): void => { + const columns = columnsController.columns.unreactive_get(); + const columnsVisibility = columns.map((column) => column.visible); + + expect(columnsVisibility).toEqual(visibility); +}; diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.test.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.test.ts new file mode 100644 index 000000000000..ddb15d4ca7e1 --- /dev/null +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.test.ts @@ -0,0 +1,124 @@ +/* eslint-disable spellcheck/spell-checker */ +import { describe, expect, it } from '@jest/globals'; + +import { expectColumnVisibility, renderColumnChooser, renderColumnChooserWithToolbar } from './test-utils.test'; + +describe('ColumnChooser', () => { + describe('View', () => { + it('toolbar button', () => { + const { toolbarController, optionsController } = renderColumnChooserWithToolbar({ + toolbar: { + visible: true, + }, + columnChooser: { + enabled: true, + }, + }); + + let toolbarItems = toolbarController.items.unreactive_get(); + + expect(toolbarItems).toHaveLength(1); + expect(toolbarItems[0].name).toEqual('columnChooserButton'); + + optionsController.option('columnChooser.enabled', false); + + toolbarItems = toolbarController.items.unreactive_get(); + + expect(toolbarItems).toHaveLength(0); + }); + }); + + describe('Select mode', () => { + it('toggles column visibility on select/unselect', async () => { + const { columnChooser, columnsController } = await renderColumnChooser({ + columns: ['Column 1', 'Column 2', 'Column 3', 'Column 4'], + columnChooser: { + enabled: true, + mode: 'select', + }, + }); + const treeView = columnChooser.treeViewRef.current; + + treeView?.unselectItem(0); + expectColumnVisibility(columnsController, [false, true, true, true]); + + treeView?.selectItem(0); + expectColumnVisibility(columnsController, [true, true, true, true]); + }); + + it('toggles column visibility on selectAll/unselectAll', async () => { + const { columnsController, columnChooser } = await renderColumnChooser({ + columns: [ + { name: 'Column 1', visible: false }, + { name: 'Column 2', visible: true }, + ], + columnChooser: { + enabled: true, + mode: 'select', + }, + }); + const treeView = columnChooser.treeViewRef.current; + + treeView?.selectAll(); + expectColumnVisibility(columnsController, [true, true]); + + treeView?.unselectAll(); + expectColumnVisibility(columnsController, [false, false]); + }); + + it('toggles column visibility on selectAll/unselectAll when some column have showInColumnChooser=false', async () => { + const { columnsController, columnChooser } = await renderColumnChooser({ + columns: [ + { name: 'Column 1' }, + { name: 'Column 2', showInColumnChooser: false }, + { name: 'Column 3' }, + ], + columnChooser: { + enabled: true, + mode: 'select', + }, + }); + const treeView = columnChooser.treeViewRef.current; + + treeView?.unselectAll(); + expectColumnVisibility(columnsController, [false, true, false]); + + // make second column invisible + columnsController.columnOption( + columnsController.columns.unreactive_get()[1], + 'visible', + false, + ); + + treeView?.selectAll(); + expectColumnVisibility(columnsController, [true, false, true]); + }); + + it('does not toggle columns with allowHiding=false on selectAll/unselectAll', async () => { + const { columnsController, columnChooser } = await renderColumnChooser({ + columns: [ + { name: 'Column 1' }, + { name: 'Column 2', allowHiding: false }, + ], + columnChooser: { + enabled: true, + mode: 'select', + }, + }); + const treeView = columnChooser.treeViewRef.current; + + treeView?.unselectAll(); + expectColumnVisibility(columnsController, [false, true]); + + // make second column invisible + columnsController.columnOption( + columnsController.columns.unreactive_get()[1], + 'visible', + false, + ); + + treeView?.selectAll(); + expectColumnVisibility(columnsController, [true, true]); + }); + }); +}); diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.tsx b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.tsx new file mode 100644 index 000000000000..633a1d3d23c8 --- /dev/null +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.tsx @@ -0,0 +1,215 @@ +/* eslint-disable spellcheck/spell-checker */ +import type { ColumnChooserMode } from '@js/common/grids'; +import messageLocalization from '@js/localization/message'; +import type { Properties as ButtonProperties } from '@js/ui/button'; +import type { Properties as PopupProperties, ShownEvent } from '@js/ui/popup'; +import type dxPopup from '@js/ui/popup'; +import { current, isGeneric, isMaterial } from '@js/ui/themes'; +import type { Properties as TreeViewProperties } from '@js/ui/tree_view'; +import type dxTreeView from '@js/ui/tree_view'; +import type { MapMaybeSubscribable, SubsGets } from '@ts/core/reactive/index'; +import { combined, computed, state } from '@ts/core/reactive/index'; +import { createRef } from 'inferno'; + +import { CLASSES as ContentViewClasses } from '../content_view/content_view'; +import { View } from '../core/view'; +import { OptionsController } from '../options_controller/options_controller'; +import { ToolbarController } from '../toolbar/controller'; +import type { PredefinedToolbarItem } from '../toolbar/types'; +import type { ColumnChooserProps } from './column_chooser'; +import { ColumnChooser } from './column_chooser'; +import { ColumnChooserController } from './controller'; + +const CLASS = { + root: 'column-chooser', + toolbarBtn: 'column-chooser-button', + list: 'column-chooser-list', + plain: 'column-chooser-plain', + dragMode: 'column-chooser-mode-drag', + selectMode: 'column-chooser-mode-select', +}; + +export class ColumnChooserView extends View { + protected override component = ColumnChooser; + + private readonly popupVisible = state(false); + + public readonly popupRef = createRef(); + + public readonly treeViewRef = createRef(); + + private readonly mode: SubsGets; + + public static dependencies = [ + ToolbarController, ColumnChooserController, OptionsController, + ] as const; + + constructor( + private readonly toolbarController: ToolbarController, + private readonly columnChooserController: ColumnChooserController, + private readonly options: OptionsController, + ) { + super(); + + this.mode = this.options.oneWay('columnChooser.mode'); + + this.toolbarController.addDefaultItem( + { + name: 'columnChooserButton', + widget: 'dxButton', + options: { + icon: 'column-chooser', + onClick: () => { this.popupVisible.update(true); }, + elementAttr: { + 'aria-haspopup': 'dialog', + class: this.addWidgetPrefix(CLASS.toolbarBtn), + }, + } as ButtonProperties, + showText: 'inMenu', + location: 'after', + locateInMenu: 'auto', + visible: true, + } as PredefinedToolbarItem, + this.options.oneWay('columnChooser.enabled'), + ); + } + + public show(): void { + this.popupVisible.update(true); + } + + public hide(): void { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this.popupRef.current?.hide(); + } + + // TODO: move it to the other place + private addWidgetPrefix(cssClass: string): string { + return `dx-cardview-${cssClass}`; + } + + protected override getProps(): SubsGets { + return combined({ + popupRef: this.popupRef, + treeViewRef: this.treeViewRef, + + visible: this.popupVisible, + mode: this.mode, + + popupConfig: combined({ + shading: false, + showCloseButton: this.isMaterialOrGeneric(), + dragEnabled: true, + resizeEnabled: true, + wrapperAttr: { + class: this.getPopupWrapperClass(), + }, + _loopFocus: true, + + width: this.options.oneWay('columnChooser.width'), + height: this.options.oneWay('columnChooser.height'), + container: this.options.oneWay('columnChooser.container'), + rtlEnabled: this.options.oneWay('rtlEnabled'), + + position: computed( + (v) => v ?? { + my: 'right bottom', + at: 'right bottom', + of: ContentViewClasses.contentView, + collision: 'fit', + offset: '-2 -2', + boundaryOffset: '2 2', + }, + [this.options.oneWay('columnChooser.position')], + ), + + toolbarItems: computed( + (title) => { + const items = [ + { text: title, toolbar: 'top', location: this.isMaterialOrGeneric() ? 'before' : 'center' }, + ]; + + if (!this.isMaterialOrGeneric()) { + // @ts-expect-error + items.push({ shortcut: 'cancel' }); + } + + return items; + }, + [this.options.oneWay('columnChooser.title')], + ), + + onShown: (e: ShownEvent) => { this.setPopupAttributes(e?.component); }, + onHidden: () => { this.popupVisible.update(false); }, + } as MapMaybeSubscribable), + + treeViewConfig: combined({ + dataStructure: 'plain', + activeStateEnabled: true, + focusStateEnabled: true, + hoverStateEnabled: true, + disabled: false, + rootValue: null, + rtlEnabled: this.options.oneWay('rtlEnabled'), + + searchEditorOptions: this.options.oneWay('columnChooser.search.editorOptions'), + searchEnabled: this.options.oneWay('columnChooser.search.enabled'), + searchTimeout: this.options.oneWay('columnChooser.search.timeout'), + + ...this.getTreeViewConfig(), + } as MapMaybeSubscribable), + }); + } + + protected getTreeViewConfig(): MapMaybeSubscribable { + if (this.isSelectMode()) { + const controller = this.columnChooserController; + + return { + items: controller.items, + showCheckBoxesMode: computed( + (v) => (v ? 'selectAll' : 'normal'), + [this.options.oneWay('columnChooser.selection.allowSelectAll')], + ), + selectByClick: this.options.oneWay('columnChooser.selection.selectByClick'), + onSelectionChanged: controller.onSelectionChanged.bind(controller), + }; + } + + return {}; + } + + private isMaterialOrGeneric(): boolean { + const theme = current(); + + return isMaterial(theme) || isGeneric(theme); + } + + private getPopupWrapperClass(): string { + const modeSpecificClass = this.isSelectMode() ? CLASS.selectMode : CLASS.dragMode; + + return [this.addWidgetPrefix(CLASS.root), this.addWidgetPrefix(modeSpecificClass)].join(' '); + } + + private setPopupAttributes(popup: dxPopup): void { + // TODO: band columns aren't yet implemented in cardview + const isBandColumnsUsed = false; + + // @ts-expect-error + popup.setAria({ + label: messageLocalization.format('dxDataGrid-columnChooserTitle'), + }); + + // @ts-expect-error + popup.$content().addClass(this.addWidgetPrefix(CLASS.list)); + + if (this.isSelectMode() && !isBandColumnsUsed) { + // @ts-expect-error + popup.$content().addClass(this.addWidgetPrefix(CLASS.plain)); + } + } + + private isSelectMode(): boolean { + return this.mode.unreactive_get() === 'select'; + } +} diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/options.ts b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/options.ts index 72796d7fc786..0aea78a31658 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/options.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/options.ts @@ -32,10 +32,12 @@ export const defaultColumnProperties = { visible: true, allowReordering: true, allowSorting: true, + allowHiding: true, allowFiltering: true, allowHeaderFiltering: true, trueText: messageLocalization.format('dxDataGrid-trueText'), falseText: messageLocalization.format('dxDataGrid-falseText'), + showInColumnChooser: true, } satisfies Partial; export const defaultColumnPropertiesByDataType: Record< diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/types.ts b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/types.ts index ee36cd4e12fe..3be3fc5f738e 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/types.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/types.ts @@ -12,11 +12,13 @@ type InheritedColumnProps = | 'visible' | 'visibleIndex' | 'allowReordering' + | 'allowHiding' | 'allowFiltering' | 'allowHeaderFiltering' | 'trueText' | 'falseText' - | 'caption'; + | 'caption' + | 'showInColumnChooser'; export type Column = Pick, InheritedColumnProps> & { dataField?: string; diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/options.ts b/packages/devextreme/js/__internal/grids/new/grid_core/options.ts index 75b9bfae7f1e..2c6f26bbb251 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/options.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/options.ts @@ -2,6 +2,7 @@ import browser from '@js/core/utils/browser'; import { isMaterialBased } from '@js/ui/themes'; import type { WidgetOptions } from '@js/ui/widget/ui.widget'; +import * as columnChooser from './column_chooser/index'; import * as columnsController from './columns_controller/index'; import * as contentView from './content_view/index'; import * as dataController from './data_controller/index'; @@ -33,6 +34,7 @@ export type Options = & selection.Options // TODO: Remove this mock search options during search implementation & SearchProperties + & columnChooser.Options & toolbar.Options; export const defaultOptions = { @@ -44,6 +46,7 @@ export const defaultOptions = { ...headerFilter.defaultOptions, ...contentView.defaultOptions, ...searchPanel.defaultOptions, + ...columnChooser.defaultOptions, ...selection.defaultOptions, searchText: '', } satisfies Options; diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/widget.ts b/packages/devextreme/js/__internal/grids/new/grid_core/widget.ts index 7d3fa0f48a11..cf168d3afb54 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/widget.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/widget.ts @@ -9,6 +9,7 @@ import type { Subscription } from '@ts/core/reactive/index'; import { SearchView } from '@ts/grids/new/grid_core/search/view'; import { render } from 'inferno'; +import * as ColumnChooserModule from './column_chooser/index'; import { CompatibilityColumnsController } from './columns_controller/compatibility'; import * as ColumnsControllerModule from './columns_controller/index'; import * as DataControllerModule from './data_controller/index'; @@ -50,6 +51,10 @@ export class GridCoreNewBase< private pagerView!: PagerView; + private columnChooserController!: ColumnChooserModule.ColumnChooserController; + + protected columnChooserView!: ColumnChooserModule.ColumnChooserView; + private toolbarController!: ToolbarController; private toolbarView!: ToolbarView; @@ -78,6 +83,8 @@ export class GridCoreNewBase< this.diContext.register(PagerView); this.diContext.register(SearchController); this.diContext.register(SearchView); + this.diContext.register(ColumnChooserModule.ColumnChooserController); + this.diContext.register(ColumnChooserModule.ColumnChooserView); this.diContext.register(FilterControllerModule.FilterController); this.diContext.register(FilterControllerModule.FilterPanelView); this.diContext.register(FilterPanelView); @@ -105,6 +112,8 @@ export class GridCoreNewBase< this.pagerView = this.diContext.get(PagerView); this.searchController = this.diContext.get(SearchController); this.searchView = this.diContext.get(SearchView); + this.columnChooserController = this.diContext.get(ColumnChooserModule.ColumnChooserController); + this.columnChooserView = this.diContext.get(ColumnChooserModule.ColumnChooserView); this.errorController = this.diContext.get(ErrorController); this.filterController = this.diContext.get(FilterControllerModule.FilterController); this.filterPanelView = this.diContext.get(FilterControllerModule.FilterPanelView); @@ -167,8 +176,10 @@ export class GridCoreNew extends ColumnsControllerModule.PublicMethods( DataControllerModule.PublicMethods( SortingControllerModule.PublicMethods( FilterControllerModule.PublicMethods( - SelectionControllerModule.PublicMethods( - GridCoreNewBase, + ColumnChooserModule.PublicMethods( + SelectionControllerModule.PublicMethods( + GridCoreNewBase, + ), ), ), ), From f9d4ab0d07de810862f81541089a8738ca90da86 Mon Sep 17 00:00:00 2001 From: Roman Semenov Date: Mon, 7 Apr 2025 22:00:41 +0400 Subject: [PATCH 2/5] fix: snap, test rename --- .../new/card_view/__snapshots__/widget.test.ts.snap | 1 + .../new/grid_core/column_chooser/controller.test.ts | 2 +- .../{test-utils.test.ts => test-utils.ts} | 2 ++ .../grids/new/grid_core/column_chooser/view.test.ts | 2 +- .../__snapshots__/columns_controller.test.ts.snap | 6 ++++++ .../__snapshots__/options.test.ts.snap | 12 ++++++++++++ .../__snapshots__/items_controller.test.ts.snap | 8 ++++++++ .../selection/__snapshots__/options.test.ts.snap | 4 ++-- 8 files changed, 33 insertions(+), 4 deletions(-) rename packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/{test-utils.test.ts => test-utils.ts} (96%) diff --git a/packages/devextreme/js/__internal/grids/new/card_view/__snapshots__/widget.test.ts.snap b/packages/devextreme/js/__internal/grids/new/card_view/__snapshots__/widget.test.ts.snap index 23187a4262ea..c684f0dd7cdb 100644 --- a/packages/devextreme/js/__internal/grids/new/card_view/__snapshots__/widget.test.ts.snap +++ b/packages/devextreme/js/__internal/grids/new/card_view/__snapshots__/widget.test.ts.snap @@ -181,5 +181,6 @@ exports[`common initial render should be successfull 1`] = `
+ `; diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts index f40b1a32a918..e8b3fd765864 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts @@ -6,7 +6,7 @@ import { ColumnsController } from '../columns_controller'; import type { Options } from '../options'; import { OptionsControllerMock } from '../options_controller/options_controller.mock'; import { ColumnChooserController } from './controller'; -import { expectColumnVisibility } from './test-utils.test'; +import { expectColumnVisibility } from './test-utils'; const createColumnChooserController = (options?: Options): { controller: ColumnChooserController; diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/test-utils.test.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/test-utils.ts similarity index 96% rename from packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/test-utils.test.ts rename to packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/test-utils.ts index 20aa2a391e09..f396f4071c89 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/test-utils.test.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/test-utils.ts @@ -1,4 +1,5 @@ /* eslint-disable spellcheck/spell-checker */ +// eslint-disable-next-line import/no-extraneous-dependencies import { expect } from '@jest/globals'; import { ColumnsController } from '../columns_controller'; @@ -9,6 +10,7 @@ import { ToolbarView } from '../toolbar/view'; import { ColumnChooserController } from './controller'; import { ColumnChooserView } from './view'; +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type const createToolbarView = (optionsController: OptionsControllerMock) => { const toolbarElement = document.createElement('div'); const toolbarController = new ToolbarController(optionsController); diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.test.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.test.ts index ddb15d4ca7e1..2c32e42a6b1b 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.test.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.test.ts @@ -1,7 +1,7 @@ /* eslint-disable spellcheck/spell-checker */ import { describe, expect, it } from '@jest/globals'; -import { expectColumnVisibility, renderColumnChooser, renderColumnChooserWithToolbar } from './test-utils.test'; +import { expectColumnVisibility, renderColumnChooser, renderColumnChooserWithToolbar } from './test-utils'; describe('ColumnChooser', () => { describe('View', () => { diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/__snapshots__/columns_controller.test.ts.snap b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/__snapshots__/columns_controller.test.ts.snap index e71a7eea318e..224c371d5d23 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/__snapshots__/columns_controller.test.ts.snap +++ b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/__snapshots__/columns_controller.test.ts.snap @@ -6,6 +6,7 @@ exports[`ColumnsController columns should contain processed column configs 1`] = "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -27,6 +28,7 @@ exports[`ColumnsController columns should contain processed column configs 1`] = }, "headerItemTemplate": undefined, "name": "a", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 0, @@ -35,6 +37,7 @@ exports[`ColumnsController columns should contain processed column configs 1`] = "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -56,6 +59,7 @@ exports[`ColumnsController columns should contain processed column configs 1`] = }, "headerItemTemplate": undefined, "name": "b", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 1, @@ -64,6 +68,7 @@ exports[`ColumnsController columns should contain processed column configs 1`] = "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -85,6 +90,7 @@ exports[`ColumnsController columns should contain processed column configs 1`] = }, "headerItemTemplate": undefined, "name": "c", + "showInColumnChooser": true, "trueText": "true", "visible": false, "visibleIndex": 2, diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/__snapshots__/options.test.ts.snap b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/__snapshots__/options.test.ts.snap index edd6e47bde76..bdd27340a613 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/__snapshots__/options.test.ts.snap +++ b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/__snapshots__/options.test.ts.snap @@ -6,6 +6,7 @@ exports[`Options columns when given as object should be normalized 1`] = ` "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -27,6 +28,7 @@ exports[`Options columns when given as object should be normalized 1`] = ` }, "headerItemTemplate": undefined, "name": "a", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 0, @@ -35,6 +37,7 @@ exports[`Options columns when given as object should be normalized 1`] = ` "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -56,6 +59,7 @@ exports[`Options columns when given as object should be normalized 1`] = ` }, "headerItemTemplate": undefined, "name": "b", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 1, @@ -64,6 +68,7 @@ exports[`Options columns when given as object should be normalized 1`] = ` "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -85,6 +90,7 @@ exports[`Options columns when given as object should be normalized 1`] = ` }, "headerItemTemplate": undefined, "name": "c", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 2, @@ -98,6 +104,7 @@ exports[`Options columns when given as string should be normalized 1`] = ` "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -119,6 +126,7 @@ exports[`Options columns when given as string should be normalized 1`] = ` }, "headerItemTemplate": undefined, "name": "a", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 0, @@ -127,6 +135,7 @@ exports[`Options columns when given as string should be normalized 1`] = ` "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -148,6 +157,7 @@ exports[`Options columns when given as string should be normalized 1`] = ` }, "headerItemTemplate": undefined, "name": "b", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 1, @@ -156,6 +166,7 @@ exports[`Options columns when given as string should be normalized 1`] = ` "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -177,6 +188,7 @@ exports[`Options columns when given as string should be normalized 1`] = ` }, "headerItemTemplate": undefined, "name": "c", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 2, diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/items_controller/__snapshots__/items_controller.test.ts.snap b/packages/devextreme/js/__internal/grids/new/grid_core/items_controller/__snapshots__/items_controller.test.ts.snap index 25afd10b1355..bddd204dc5a6 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/items_controller/__snapshots__/items_controller.test.ts.snap +++ b/packages/devextreme/js/__internal/grids/new/grid_core/items_controller/__snapshots__/items_controller.test.ts.snap @@ -8,6 +8,7 @@ exports[`ItemsController createDataRow should process data object to data row us "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -29,6 +30,7 @@ exports[`ItemsController createDataRow should process data object to data row us }, "headerItemTemplate": undefined, "name": "a", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 0, @@ -43,6 +45,7 @@ exports[`ItemsController createDataRow should process data object to data row us "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -64,6 +67,7 @@ exports[`ItemsController createDataRow should process data object to data row us }, "headerItemTemplate": undefined, "name": "b", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 1, @@ -93,6 +97,7 @@ exports[`ItemsController createDataRow should process data object to data row us "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -114,6 +119,7 @@ exports[`ItemsController createDataRow should process data object to data row us }, "headerItemTemplate": undefined, "name": "a", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 0, @@ -128,6 +134,7 @@ exports[`ItemsController createDataRow should process data object to data row us "alignment": "left", "allowFiltering": true, "allowHeaderFiltering": false, + "allowHiding": true, "allowReordering": true, "allowSorting": true, "calculateCellValue": [Function], @@ -149,6 +156,7 @@ exports[`ItemsController createDataRow should process data object to data row us }, "headerItemTemplate": undefined, "name": "b", + "showInColumnChooser": true, "trueText": "true", "visible": true, "visibleIndex": 1, diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/selection/__snapshots__/options.test.ts.snap b/packages/devextreme/js/__internal/grids/new/grid_core/selection/__snapshots__/options.test.ts.snap index 450dc1044be7..d80db2503b5a 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/selection/__snapshots__/options.test.ts.snap +++ b/packages/devextreme/js/__internal/grids/new/grid_core/selection/__snapshots__/options.test.ts.snap @@ -70,7 +70,7 @@ exports[`Options selection allowSelectAll when it is true and selection mode is "disabled": false, "icon": "selectall", "onClick": [Function], - "text": "Select All", + "text": "", }, "widget": "dxButton", }, @@ -82,7 +82,7 @@ exports[`Options selection allowSelectAll when it is true and selection mode is "disabled": true, "icon": "close", "onClick": [Function], - "text": "Clear selection", + "text": "", }, "widget": "dxButton", }, From 199dbed368e2fb0ae75611d82d951e5c0353ecac Mon Sep 17 00:00:00 2001 From: Roman Semenov Date: Wed, 9 Apr 2025 09:27:45 +0400 Subject: [PATCH 3/5] snap --- .../grid_core/selection/__snapshots__/options.test.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/selection/__snapshots__/options.test.ts.snap b/packages/devextreme/js/__internal/grids/new/grid_core/selection/__snapshots__/options.test.ts.snap index d80db2503b5a..450dc1044be7 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/selection/__snapshots__/options.test.ts.snap +++ b/packages/devextreme/js/__internal/grids/new/grid_core/selection/__snapshots__/options.test.ts.snap @@ -70,7 +70,7 @@ exports[`Options selection allowSelectAll when it is true and selection mode is "disabled": false, "icon": "selectall", "onClick": [Function], - "text": "", + "text": "Select All", }, "widget": "dxButton", }, @@ -82,7 +82,7 @@ exports[`Options selection allowSelectAll when it is true and selection mode is "disabled": true, "icon": "close", "onClick": [Function], - "text": "", + "text": "Clear selection", }, "widget": "dxButton", }, From d73b325a94a174e0889e9d5db3bb6b20c12769b4 Mon Sep 17 00:00:00 2001 From: Roman Semenov Date: Wed, 9 Apr 2025 09:30:06 +0400 Subject: [PATCH 4/5] gen: etalons --- ...-view_column-chooser (fluent-blue-light).png | Bin 0 -> 13178 bytes ...card-view_column-chooser (generic-light).png | Bin 0 -> 12901 bytes ...iew_column-chooser (material-blue-light).png | Bin 0 -> 12106 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 e2e/testcafe-devextreme/tests/cardView/columnChooser/etalons/card-view_column-chooser (fluent-blue-light).png create mode 100644 e2e/testcafe-devextreme/tests/cardView/columnChooser/etalons/card-view_column-chooser (generic-light).png create mode 100644 e2e/testcafe-devextreme/tests/cardView/columnChooser/etalons/card-view_column-chooser (material-blue-light).png diff --git a/e2e/testcafe-devextreme/tests/cardView/columnChooser/etalons/card-view_column-chooser (fluent-blue-light).png b/e2e/testcafe-devextreme/tests/cardView/columnChooser/etalons/card-view_column-chooser (fluent-blue-light).png new file mode 100644 index 0000000000000000000000000000000000000000..50f1a51a6783e8310bf3606c3d4a396e33372579 GIT binary patch literal 13178 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 literal 0 HcmV?d00001 diff --git a/e2e/testcafe-devextreme/tests/cardView/columnChooser/etalons/card-view_column-chooser (material-blue-light).png b/e2e/testcafe-devextreme/tests/cardView/columnChooser/etalons/card-view_column-chooser (material-blue-light).png new file mode 100644 index 0000000000000000000000000000000000000000..e02c71ffb9031bd50f2197d41aeb081c4f6673f7 GIT binary patch literal 12106 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 Date: Wed, 9 Apr 2025 11:52:39 +0400 Subject: [PATCH 5/5] review fix: remove misplaced etalons --- ...-view_column-chooser (fluent-blue-light).png | Bin 13178 -> 0 bytes ...iew_column-chooser (material-blue-light).png | Bin 12106 -> 0 bytes .../etalons/card-view_column-chooser.png | Bin 12901 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 e2e/testcafe-devextreme/tests/cardView/etalons/card-view_column-chooser (fluent-blue-light).png delete mode 100644 e2e/testcafe-devextreme/tests/cardView/etalons/card-view_column-chooser (material-blue-light).png delete mode 100644 e2e/testcafe-devextreme/tests/cardView/etalons/card-view_column-chooser.png diff --git a/e2e/testcafe-devextreme/tests/cardView/etalons/card-view_column-chooser (fluent-blue-light).png b/e2e/testcafe-devextreme/tests/cardView/etalons/card-view_column-chooser (fluent-blue-light).png deleted file mode 100644 index 50f1a51a6783e8310bf3606c3d4a396e33372579..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13178 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