From 3d08a3aaef1c22bc97788380a1f33dca091ecf35 Mon Sep 17 00:00:00 2001 From: dmitrykurmanov Date: Fri, 25 Aug 2023 19:42:25 +0400 Subject: [PATCH 1/8] fixed https://github.com/surveyjs/survey-creator/issues/3340 --- src/dragdrop/dom-adapter.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dragdrop/dom-adapter.ts b/src/dragdrop/dom-adapter.ts index 03fc4d0bc1..17f1518e1b 100644 --- a/src/dragdrop/dom-adapter.ts +++ b/src/dragdrop/dom-adapter.ts @@ -39,6 +39,9 @@ export class DragDropDOMAdapter implements IDragDropDOMAdapter { private scrollIntervalId: number = null; constructor(private dd: IDragDropEngine, private longTap?: boolean) { + if (typeof longTap === "undefined") { + longTap = true; + } } private get rootElement() { if(isShadowDOM(settings.environment.root)) { From 1f2a721c48c52357af291ae85e3c378ffa69109d Mon Sep 17 00:00:00 2001 From: Dmitry Kurmanov Date: Mon, 28 Aug 2023 11:11:52 +0400 Subject: [PATCH 2/8] PR: Ranking: New Issues (#6772) * work for the https://github.com/surveyjs/private-tasks/issues/267 (animations) * work for the https://github.com/surveyjs/private-tasks/issues/267 (design time dnd with selectToRankEnabled) * work for the https://github.com/surveyjs/private-tasks/issues/267 (ui width issue) * work for the https://github.com/surveyjs/private-tasks/issues/267 (update screenshot) * work for the https://github.com/surveyjs/private-tasks/issues/267 (added u test) --- src/common-styles/sv-ranking.scss | 21 +++++++++--- src/defaultV2-theme/blocks/sd-ranking.scss | 32 ++++++++++++++++++ src/dragdrop/choices.ts | 8 ++++- tests/dragdrophelpertests.ts | 18 ++++++++++ .../question-ranking-select-to-rank.png | Bin 27762 -> 27750 bytes 5 files changed, 73 insertions(+), 6 deletions(-) diff --git a/src/common-styles/sv-ranking.scss b/src/common-styles/sv-ranking.scss index a4b66bf438..cd8138b38e 100644 --- a/src/common-styles/sv-ranking.scss +++ b/src/common-styles/sv-ranking.scss @@ -227,6 +227,9 @@ .sv-ranking__container--empty { padding-top: calcSize(1); padding-bottom: calcSize(1); + display: flex; + justify-content: center; + align-items: center; } } @@ -243,15 +246,23 @@ .sv-ranking__container--empty { &.sv-ranking__container--to { - padding-right: calcSize(3); + //padding-right: calcSize(3); .sv-ranking-item { left: initial; } + + .sv-ranking__container-placeholder { + padding-left: calcSize(5); + } } &.sv-ranking__container--from { - padding-left: calcSize(3); + //padding-left: calcSize(3); + + .sv-ranking__container-placeholder { + padding-right: calcSize(5); + } } } } @@ -263,17 +274,17 @@ display: flex; justify-content: center; align-items: center; - width: 100%; + //width: 100%; height: 100%; } .sv-ranking__container { flex: 1; - max-width: 100%; + //max-width: 100%; } .sv-ranking__container--empty { - padding: calcSize(8); + //padding: calcSize(8); box-sizing: border-box; text-align: center; } diff --git a/src/defaultV2-theme/blocks/sd-ranking.scss b/src/defaultV2-theme/blocks/sd-ranking.scss index 7e5ac415af..cfd050173d 100644 --- a/src/defaultV2-theme/blocks/sd-ranking.scss +++ b/src/defaultV2-theme/blocks/sd-ranking.scss @@ -29,4 +29,36 @@ .sv-ranking-item__content.sd-ranking-item__content { line-height: calcLineHeight(1.5); +} + +.sv-dragdrop-movedown { + transform: translate(0, 0); + animation: svdragdropmovedown 0.1s; + animation-timing-function: ease-in-out; +} + +@keyframes svdragdropmovedown { + 0% { + transform: translate(0, -50px); + } + + 100% { + transform: translate(0, 0); + } +} + +.sv-dragdrop-moveup { + transform: translate(0, 0); + animation: svdragdropmoveup 0.1s; + animation-timing-function: ease-in-out; +} + +@keyframes svdragdropmoveup { + 0% { + transform: translate(0, 50px); + } + + 100% { + transform: translate(0, 0); + } } \ No newline at end of file diff --git a/src/dragdrop/choices.ts b/src/dragdrop/choices.ts index 4589b619d4..29991cf49d 100644 --- a/src/dragdrop/choices.ts +++ b/src/dragdrop/choices.ts @@ -106,7 +106,13 @@ export class DragDropChoices extends DragDropCore { private getVisibleChoices() { const parent = this.parentElement; - if (parent.getType() === "ranking") return parent.rankingChoices; + if (parent.getType() === "ranking") { + if (parent.selectToRankEnabled) { + return parent.visibleChoices; + } else { + return parent.rankingChoices; + } + } return parent.visibleChoices; } diff --git a/tests/dragdrophelpertests.ts b/tests/dragdrophelpertests.ts index cd4f047424..33af1ca621 100644 --- a/tests/dragdrophelpertests.ts +++ b/tests/dragdrophelpertests.ts @@ -365,4 +365,22 @@ QUnit.test("rows: check matrixdynamic d&d", function (assert) { ddHelper.clear(); assert.strictEqual(question.renderedTable.rows[1].row, question.visibleRows[0]); assert.strictEqual(question.renderedTable.rows[3].row, question.visibleRows[1]); +}); + +QUnit.test("ranking selectToRank for ChoicesDND(creator)", function (assert) { + const json = { + questions: [ + { + type: "ranking", + name: "q1", + selectToRankEnabled: true, + choices: ["item1", "item2", "item3", "item4"] + }, + ], + }; + const survey = new SurveyModel(json); + + let ddHelper:any = new DragDropChoices(survey); + ddHelper.parentElement = survey.getQuestionByName("q1"); + assert.equal(ddHelper["getVisibleChoices"]().length, 4); }); \ No newline at end of file diff --git a/visualRegressionTests/tests/defaultV2/etalons/question-ranking-select-to-rank.png b/visualRegressionTests/tests/defaultV2/etalons/question-ranking-select-to-rank.png index f2f997e481bd49755ca672004fa68fcf45bb35ec..4b7d9dfad25145671c075307a405f3ac4faec5d5 100644 GIT binary patch delta 15987 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 Pz#nCK4Y?08=CA)3KwI^? delta 15999 zcmb_@byQW~x38ddcXvv+#Gy;NRJywxDcK<1(%mIWA3z$E?owKWLkj{2P(X>d!SB2G zci+8ty!*y@{&Co>GuP}jKXc8E+Y1OM3kYu*5#s8Z^tpikqi$!_3l|&ez(a<0@6hvI zmX;Ir#Gn^fRaT2Sq|NmeqDll62-!RWbdQgLe54jqaBJ>axQGGN&>)LL=o%ZH>z5?$mSLkp@j3}{b|MyaB3caZn45J`&ZSa-6roh{e? z(9PJEXPQ#du7zF(W?R#TiLUg}@2QYnR{nVOq!tUneO?tk)78*3Z_AY=kz_{Oqcd7s zvHl&nj_;MoH(>PMqnB*TTib3zD2@@-TGA!H_&vrn!-9|b$hSIcSS+{m`bmUL%zRsp zr4s^7H((Fm8p8UJCBf5uTQt_Fx7v5zC2MGW*(i!Ff7iu!Z=Zi9vwO5GA2(krRSLz? zU=JOTkM{SCRtwrBeMORi`s!A<<|mS-6CLg+yU^In_GifwD;Rz=jl8(%YxXL*>x|G- zBJA^)RxwE=QaLfAoE1)jR=*q!t$u>9KR8~!il8`s+4`9PhDNlt@+@_yn5t^?wr_YE zg0WK^wvs0&YaCZ!&LAZ~4vRlbk6!5*4}S{-q7Qx2yCiz!FWZg2qrtUr9-(bM0)9OMq`6Eq3#?iT4?D&j5dP*tNVw6+O;30|q-LFA~o zpT|1|g?Zz|6%oQSl4^h8G%c@+P;lCFQu1m#8SpI?ewp>N!iP44ppVlV@(LQxg^20cgA#2oolIN+H%QSPsWn1QV9>f=5b zM+$T*Ee_W#0FU8yqAlT}&zzN>frZ+?^Fx1m$}h#TGMX~FHMHfiIWmRKv6;aNr3#gM z3eRm%doj03@)+9rls+u7BK1?R<=01|eiO5E*c`p+hV3~lO_;{Rs0b#gLp>D7xGD}L_9)Zki&thZjDN10b;F4yUMu72x;w`w!!Kx8Iz!3 z(85%E6yhQ7w8giMyN@DYb!fJ#1R?K+1zb|L8YLKUDQ5YYg??X}6UFJ75fr|sVT6;dhW6HKK}meIMTFGN_!aG= z@dPhIUb0JVab1!X5*%)MZhDA#v{G6xg&>`%SPR9F z;sruV+&(~=duQ-9R*W-k$d0Qx{#vROx5iqVFmzpdQQ6S{=uX5CVGz zr9TcHNgC~b96a2y7=+gA&mInpx9gjep-ykFe{EqP?c@;=mA`3cExIC{4>4hQoipg< zG}qYf4h>)A8x2l8w_UEXAN*ls*gT%?v*OasqvA()44-?Uhb+_Rw=ko9NnPlh1vo>? zF%ly=7lj;`+}jsFaco)l4C+)jvNo5=d}Ul#Aj`|%3Z$2|_DR;KH;P8_O_?L^_i@S* zH1>r!nTIQ92}0w3(U_-ZEC?;177`wnHOa$ce8qlrgc5;boT-}|pKXI;-hGYF`LLa=JB`$mB)h?N`aEM)I`S~sj5&gW>OxF^XsGU}A`qp98f6qyPT$E0i<>aV9z zja0|A$d8`hpPEzAkgCr@Df4yR5)&atb*KMs8Q>yH@7}_z78DfRT&W**K2xbTD?Rj} z{B*2fmsS$P+4kXuFSujD#5&)Qz;Y#X*wgkG*JvOnb*hEoFPK0|2|?)&N#?bEwDV)3 z*RO7!V=9ZPb(whj2mm zI?S*oNXPV7F;zs{5<0?w&{!&sB0cD{BE%NI0M14P6^;x9oTDDKK4IzQc&+l23iI!x zZj@lbiY9(SJ;#yy_#w4P%V2g?q!6`Zh>%&<_yN&jy?B`(6p$+eS;P~sfK-}Xf2mOO zg;tefzayS-q#@u;E>=07H#QJ~wD+V+7%n)D#H^q=?iEY5M;a7I3i7-WZKPEB7QX^X z(uVbSyJY$XQFLMiRi3d0=jgKbXK$=r4I&lCd@YloM%v66369)xnrjNM+ajS8}+58$2UuDGQv)iD*6!U}FN9AIye^gUs#14h7s5SE; zkrr{yJtlNa__j$yQp~!VCR4wCp$6Qz)5X9DG!Y`0YZ{Kf&<@@Rpf`H%?&=4%h|4AB zB#wCczBa`#K^lyBEGMa;Unz@*p8n)YsN00b`mWZf1N@ zWxj=PH6e#jN7mGnueSo4S$wO(k|pwaG|h9Th4^?%CV%=CGQi5+J{U8OYz>THRKeF= z%tHgJ7MwK8J9@}*4vEd=i}XCNm~UHf<>BTAb`M2cPfR~N{k>p-0Y-Y%x~I2UM)vCW zK5jsCO5Vh*`df_5Y@5|>k$|9d%w{I@Zq!@BcZ)ty<*I5FMc~5b* zt2|%gen+0s*<^>tYQrjIr^Q1u0hm=g@njIsu0dFx{KK7l_ z*Luw2fr3=G?gV9JBe&r{3haPNF)ERyY?j+(Wrw?fK!>wc1c-k|S~0WmPtx_<{eF12 z!PzG-fy;l%OhkMX!p*TgYZY8F{UAo8ltHcm%VrkJapL}U<5lXg#`ptwWObHkAAh&@ zuXWnnO-`#rclZufEt^#xmpPwCmB|0TTU>#aJ_{W?{bV7bhAd2uRj9XN&(fD&hAuS8 z!IzW26%Vw@koJ5U!^9XhW<->rKJ`}EgJJ9F_@(cau@w4#nw5X~**oH*z4uP zy~ig)1w-_eMba~az#2{W%}8zcO?+h%oqu2;X%1&<)+D#~I_D#qvj?qS*+^|q9|b}- zu;rps=<+5Wy36Fnylj4B>qSN?Jg!L}Jo#hbhsipyif`CHsHioe!TYceMLi|X2j&h| zaG9*?v1AZdTb1)G1#r=(*KI=eXP~hV-C_PTWO_Q$mEellLl;_c`PJ=E@37=XUKM|z zqLS;m;I}x$o&;9uOTN$tNmeAiy(DC1@dRJ#2q!OiCi1K;w&|~xgx!UM zD^sh2u%zJAckrZy~94pE~^rT{qo)OcD{;?A?w5EbOg8}sC0`3V2Ox=hOhe`M@D>%!%6f_(Mj zNLo+JsGD>!FY7WX7)(VTUG+6TV<{3g(kQcYqyTR@ZBnQu&Y7_#fYcQm!V`^49`yoi zSWYbErGNCsHzuXV-Wi#MMMH_-<;bY@R5Sy7P}M-sBnDG%_p5fsJ9iB628=3x`}}}T zA~ka2X;^dY;6<-@zT-X*Dfwl7$eWy()6;&0nN}BLNWx1W8^k_ICF0Z#=lzLcnEyz6 zD>jc$-8?T{N}}KjjMa^~ckQnsX++6AQn%s5ZIv17ZQtMBWaaU*46C0&XfqhuWMR&7 z|4<)Ykzz+;r7+3+SwiXw`$Zfh-IJsKS+cTN%u5P}(iOBN-9tVR-u@Z7=BbIV-IVtU zT|0L5EJkT*S3Id_P~peQ^(fx&Z7|aJSy39lN`MA{)vs6hReH25m&fKlQv#5|IE}4> zA!6ftxtl{y+qbMUZ8Aae7+E8zcYTr0Kb~tPt$l1lUF(p{oN*oDWmp$9vc(+N|4F87H-Kj1~-OpRyP(8ayAU?3u;|GDuzq5ZTpB9csf%U&sP z^2drGK6O3@rqRZ>{=@St?}*637H{s6rq6=NFsI3swUO%glsFu`BBEnMefS}sA1>G1 zQFGotkgcR?^;$~EiXfw=X4Xk?^SM%V!9vpPh-i;gnSCMxG{%ST_hRDUq~xFD9yc9_q4T8vPI^E1 zbyEjitr+^icyZ&C;E0BE#3B_~m=hk3B%DnP+um?HceDS^ypz~m?*`htZaxE?QX_T| z=WEhMXiM@13CW0fCf_h9?soHhL_}*_T7*NQ9aXga9ThjAvObkm@`){RJ zK6p6q;xXsOe;+o(l~@x7Z|7iPR~TJtRL=?Ds6rH1{vN&6u^c1br(O&;0lDvk?h^_l zR_ebzH=jz9FcZ^G%Zs^|%g6$yL6kdArK;Ojl8Omup5_(^_{NQ=>jz@?%*;oHut5>v z2C_3*uyYk{g2-+k(M@La?vt21OV>u^#@Dx5TF5B3pQ_6Os&srs85*19QJX%T*xdE1 z`MW>p3Kx15ZC_F(HhI5d&H<2isV=EYETf0{ zLopM#Dyxof5Ic?9{d0R}yw$12J`G2Uc@@y?D4T}qdb|HxB9a*;h{H_eGsbqi`p!9V z-m+K~3!SgQHOM!!@=e|I2;R_jb?+J+=l^d^J{lQZcbr|hl8{yj3j1iOC=3V*E7z>3 zmv*Lk$Mk5%Ebm|$oXmqcXGtCk?>6~p#{Z!r)@NyN@2pN&nA{Q9&`>q$YF24v=XT^w z>H%GtFNMz`;_bI2E&l-kJdg^3QS#culI}D76Wk1FD;;J#6Yxled69rWx)Cx_lN^#K z0bQ-6JKw*t2p_CBoiKFo06DSlH8-zb_fq#^ugi5rs7Z(qU`FolW7CG=x>k&RUSJ({ z?j*%~0+Z#`$wz=tuQAhCd^ z@$vWemM)9#N=QtcgDq+pE)45%oS!c+Y3r9P<@HT%uEuX%noxRwm+YK;j4NxeDAz-- zhd(G|u^UWXl5Q?Gtjy+vk2Q24x@r=sSOI1-cD(K02g@*4T8}ISlN%fnk?Ht)FjM=>Hy% zjN|Z}y5@!bvAaMp%KN)VkzI%F*m9d(?7z|j!c&Y7ZoV^6SAj%u!8@YET8Y0laJ$!I zfHvIdH&xE<2Rh(5zJEsHeN&>p?j`&;8b5LmWNxc~rDyxz5*ZGi3D1qC?~UhnYZzU5 zFHvkzd)g}gZoWnL)xC52Tz0HT{PYaB%&SLS?>>5$*zP5@XQdbygD$B3j^5n_Jl6#+ zypQ|A3w599KkuKDU;QHQ2{jbBkFLsCgo0GTIycv6ORUr71LL8 zp?M_;E2h==0jZ}DSwy1#;&>py{`0v+x`#^~#)rdu2f;;z7uR3xdppDXyln>Cs2 zSh8}*C1o2Ie^S?Eev-_1{71qi4e!qD)SDKO(0xH4wsw;Zm5LM`BGL z62(+EZI>~Xs-IAsEJO3x(^0tdRzPMfRn4l|;5)(ZfkrOHvX5OpoWq|ltsQ}5vSS(R z-vZ*Y=fW8y?wo7od<8I7zTv0eiDeP``JZ%MrbB%a$nss1h=S1h_CB_MqV5E}J?*+VqPf9w-RQoBOLioR7R*9YNL;2o_ehcv zo+P$DR8q%`hwnt||K|F+X7g41>d_7kie{CT)^GK55BLIlMvxM|8&m=BDfS!4CDvuQ zr=0A4%xT;kW&sh(D8VhUO=6f=*cT5UTf}9CH6aA77~pP z+|&yP{#+gbS2zX9DU){g(U@d>rq}t>CO+vzLfUscWjYc-jfdAu=ib&62#Vwe3OWDi z+bcWDP&sS43tE`3tGbUci&#d=gxSCg55=xe=i3qc*H(qBVtQK2gfolTf~3a8FKjuZ#lsv#8Nzj;E&(#qA^EI z@SKg)kd}s?R#HAhIA*L#I#qRBpW!X$f2m&{pYRk%v0E(iz8)-l2+RR>y_~g>(mA`j z6af*+#wJQRRQRV!$=flS+Y3d|o&zU!AA~QP78RGqI(Jno47WWg#dyt3hacMq8^x_| zIQ*WK%cd2HormznC-2}q7{)xp|E>^s#4wBujL6=PuH)-&$Kj*@&~I5~xUCg_@dkpw zWw*B?p^5G9DjC&meLQ;%}_T1LAP(&6sVLD>F4g<3uxc>;b>qqq*Ju#}s zIfXBP3rZ=+Qv?HJl)qI;#pu8TCC7-;P1sM*bn6>fJ_1Qm3PFvgKgW&kf#3#~=UVrA z6tEN<Om`&TwOFSoX2qU6k^wX1JfE#wPcl68GNdfKHvVQRu_e(uz!z)?iKb z$y<{WgwGUM~Ikmr9whyVEk zNx-wt={2nq^`;jk3ZY;8^T@HN9Y2MP?vsPRU$;VKGv`ElH9R(o$pZDG%4E&z} z5g%(@1=i-m7hCHNX~;B+4}I$l?jHXQZ-Bpmqbt1F4?+hFgd$`b(|alqSMKfqg-_D1 z2^vxGJjbDPqT*LwvvQNxj$}3w81KKiF)_?_Hu+8sEW(~3*64j9`nwMd^H}G1hIcyQ>$}z}!1X)j#DvM`V!+biwVrnq$L1y58abC4X_# z1x(hKZV)kDYY{;3{F`{yxd(_%3ZcOKy8}WT-S=Qj|7I`)OMB1t7e#>u5pwY7KM-|y zWVAX5)S=p@Tb7S^23p+qvF{VL001YME=?vC-~pWdOpXO&ijg`C&ASdBh41PpEZ8q$ z+aGi$)ZFa7;wrP+IX-w#LA5C2Mv^u)z>0A7svA?lxF;UWUw%Iih4}pXRf`$!TbxT_c`=5%*FM@vBRbL(eu^2kQpN81{)jz2 zB8V*}DceQ37^P)<2za98J<-4 z=N!kqzV{1-_v-xZb?@!E^VPZJP2{=Oj%T**$tNs-u4@^-wQb&)w8POwyf+YDm2YL# zD^-Ru1#4I94`Kw_l)vqna8Vns&v1j$nqx&AMo4Dqrt5Y~u!{l*W#m*vTTU@i6!-ln zSS5T!BOlh62S%>QB(8kM1_Ic~OOKTi z&Xb~pE7W0E8$hYNt76c&NV`(A^4Z%v0--x47sNoc9a-#q<--i3n~vr*fhuO6`EHIR z&r_5g9T8;2H6J7fNoI}=ZB7qGr8Bv>+$p%+pt+6m9T6HfQq!?|I38!QK4>r$uy-D=L0rwc$@YjL>bTex1OTh?o#r$+q4rBFgnZn*TrZp8Ly zRyCSE9O-qMb~ik5J=|KD$mm$|I596LMcJOO;M}DpX;6H%o=r%r48m+<-SkwbxdpEz z`Mz@aC}E?t1>vyG4y%EX@+m>WAe#STA0N~TilnMiv=?OIF6j#N{)gXl7MQc%6MxhR zI&g|``q+ogEJAeJF!5>3W|&xw!|-lTJ!#v3j*!hZ+lynuwlq3^-BPQ^0zjr7M^w#1 zx-lEylP8MPjdf`ehlzNJd#w2lY7JQ&^0S{_kl(oF`c9475Zef;G}~D$qN|+~#P&}C zg82=+{JM{SqeSn=*dAynwYG}Hl!sRfcmZ*~s*3PTwaPb4{JMP&f*m)s^}e{=+^I48 z+uJdj=~&q$-PFvKv(pO^&dK9ekF$xJXO1H``a(^F>Qx&SIgn;$>_u<%;xcRCs{h%m z7V&=>1OLw1u%4IyF`qmJPiwAqJdGt!LXDoK4x805aZD=5R7cS3dSPj97?#lizG;gQ z2t)P)Wm*?eIcTl(FIoKlO&!OK)#5VD`)sK%yPnU+fpyK*H)34lhDz9yVfDLqLUU zMO(~0a?RX){IH*&IQ+A){8w5LyTS*{xeVg@pT2A0fA+1(RMSBp;Q74)usV&k3hcSZ zZkl0o8$!o1H^_48lB}jQ%?wkW!eLn=Gg-87UrAmhP~IM)yJAqk~UL|dW5o6Du$*s zjC3KE|L$0b<$uB3q97^0T8J~zaCuE~JP!UW-m+VR zim=<%cd)@7|GM%TcnDsl;U8097l-#_*xXr6_hV{2;+hdCz zDC$<}h<+@TFS4qqQk#df<(ZgpeZB)9QIH;H#%tufAsv;~gSa6=JiO zh6Q2uTcV3ovXm3CW(pZXStp35H;|=kVQ6LRUkJJF!Ys|b`bEnKF#qt5;|pnI-7)!B z9?dpdx$MP*Sg%d`36y)^KhCd1A0zUDxq}4(Jf=MQ=*${=&C&Dw@*8B~y7LP_zJf5Z z!o6*EG_xG$&J*{)WfAflzfd{<&4n zE(`T}$>V&@>;hk-3Lf1a8K=Qvu9J3V64N&9W5dfC?+05>Af!l;b<=RW$`;ktJ4^6k zsZzvZd2y33*8$GT%`{&}ZA`Evm+SuhnR^z#ACr-$EI%bEAT-+%#HyF-`|;?!AuD1Y zM}E{orCGjmbMVNTLewPQ`9DxCymr=NyMzZUCOfCGUS9hyKJDEPFSdqf>LyAHsg;{) zH~6XCZAz^}Upsejf&pKqRhT$(NUnl9oNNr4l!GKqgl3NYi|q6}FqYZ0PWFBMqURI4 zpM7coGpBwuaL-{IY$U;UcCxa6u`i>>2CVrd_0GqRc20%$Ozl?M9E3ca7*MPFiNpeL z6V9k?c8lMgyXbXl=t$h_r2{@r&>^GxsON0v215H5PQ{@At+o18G~xK+1410J^d_%k zGFSyn$~8O22AX@0<}VokE;_R|+gci~ojZ0Aj21^_6k4dHKM%7=dM|H61oe}_NTxiq zAjYs7m|erd2aBp;bJ0S&vkqcR<*1ckRsk)AUB{<}7)=h3rlI#1LPy~98dfpxQExw2 zDIoaaxSRd9Ts?I1J0$I#kt(r| zUwj#bl>1#jif5FLpKm~aJP<1yVP42SmxgYn4tEj2l9YF%&~&muAg?X5zj$o19Be^= zG384TK2vC?-v>WoZXSQ{Bvmh{)~kWH3?LI8DHRE@8W6j8bo^aHCaj$jkbHEV8?)!6 z;x`@Y{yUUcxt}8oF0c;5A?%tpJR(EyuHuNz{zDeXs&*h`W znKo!S-aeI5&1NOOx+YiV@vR4x<>R95a^^L_(65e*UUJVx5mk^R`jb)8hjNtYBqn}a z3+RN<&Jb7(J}(YAjwd}fSb*4APFN4&GrT<|H@R|`v|*O5w}MWTKWp%1@qa_A&*#Z3 zwD07Zph|2ZomcG#AH2@Y!t75T7tPTghM|pX=y4~jldvvAtS!@2m4!4Gm{O9hPk}gN zHf`4LtnoO-k(LWt0{XL`wjVEl5>V+#+GeRDQL4a5b;@t3S7v6)nV(6;?#E{mntB}; z%ABQ&H@c0s%$7Wy`KVV~pwH+3HaCz^O&aq}!rT|AO_-}R7{a!?vmPMhkI_Fc1<88YykV>Lp7XE8B-Jh?4l1fxuQW7Ua+as)&)Dt z)QB1sv_W6atwhUIJ}WNUdI3oVzJwa7L@WzJJ}Yf9Wnw!MNomVBg(Prfus#13C5m;Z zO9MYzV#8XE2WKfS)wsIc1ULFZaA9AsuTCeg;E8}-pbK%h7x5?!^TBzso~_|s=i=l0 zrln?~+X)yOdmeKm4QrD@Md12{%YqH&xt+61(b8MX`4@iAYNsE76M=Yz&_S@%!tU8~ zbL*K7bMTlx@B(Kr?b^ePu?5oIB>fo5v+w}(32-Aj@e+ke9o7>TFe446fYbRTXOkoSJj1CZfDukjmv4L|D z0bj}Y@uKIt`{3oqW9rKoiQ2d@)jzVy!8sfN$~JwUsAu9g6#9h?OTy@G_G9h0MR#lP zO0M&6INx_;L!?cpj9PE|-_3{)Y=xMhpeE6=#&5x4)8A2$PJo_a+0xrnnsM~|_a9Lj z{R3l0{pk6hTy2M~Ffw1f*{mcr=>hmK#)!}}%fsU%s4)p*FQ@f%*^J5yvG7Zt3W+IB zH)v%SxIxsXMun6KXUJ5)_MkdAS>%9u7(;Ak!aPde{n5-w5uW-#x&X{+WFjs)A~^%|L4`E+u=G6f?kYV61%T!m{rVO7z2K5k=871uXIlBEvdfe*2g< zX}-5`^fH2@C&wm#FQeR940&kyiRT15!Onac>Pf(hP|~1&f)^p5eeu3N^%&7K%NZ-v zvD#&+VbAA<+M^CcpATy4Wo8lXHHO!8JleSKBfRUmy&_He41!K zRh{QxP(Wp&iXTHisvm7Xh9y;9xJoCN-2(o)Iy@Swla+dQs@J@Oi9#Ig8X-kzwC3H> z`VDw6S>Z)_>bVzwdhbsR?>_39W9}TMc)riN8i8CM-;dlz692)HNV`;7`uB!t%z4?y zmjwm1_rQao+5u)0s!p)O^85H6^sl|0ogF%zgeXZnn15@gUxVlAQFj+h1$6Lht@atsNg-f1?QC8QMrA?(Ii=r%FUvq5!W6gQ1;ggX+>rO`B~@0Kyo9a z{&VGznNRq;k2dnI+gVR231iRdQl5MxTW_K+T|pHHQAmf^X)$nv@1kZnWRn}o4m~y| zKloaIb39->!TIu?GknW}&VQ8MbNySC>@o@A zd|!}JDW@nhKhJGrfb(78d;fh53E;9=Imxyu<(2E<#^Dvq%G(o-GtCtwpvyb9qTcaa z&NGtj%gq7fcYziD85B=k=sH=^)Xc=4-#l@&r`k1RsNzuP?>tdq#y(O=KD+(l?-}+A z1LJDm^+=oZ*YQZ#^?~H)UY738QU2via@Q`A(Ss|J4*nBz@hiO~-Cs1YxlaIM_w^>1 zcrB%c)h$=dm7I7j?}<8&>D446^z=gu#@Rt&xN+?dOOlybJnO_amOllyfO(o^#oN{T zaK=aZU&{7w%{G_xiCH2a!;7ox1fGnJoka$oUGhy0?kld^96Yg(FqQeORAbcoDPKI` z4da%f%*69qWWVQX6iyf+wt{ZJ89x_XJS{dZjXiFhvOHtF-eX;W0OMhtTHekxR~F6n znK9u(?A47GTLMg?Bt|7p`Zu0UjnXDxW|1dlf6mBDSb6@W&V+qxEx|lGEPKYL#n#!U z=@*wI)@`}Rm&{lh&bVo$tYA{+6jxSBMY#$2FnZ0QPPNg=PxG+b_9)>c;CIk>xtxk} zIWPhfU>U5)><)_Tnoo2)JA0gfoqjQg?pYF`&t+Z|gsAJ69w&^$!II_FR!_?K(aVuPb zjib4l1j8+{boJb>7G$nX;L(I7(LZERB=b9>Rmor>CEpZNQN6vQwe_tkkgb^T_%%c; z�u$t~Aun`kJHUN41e9{3Hk)EB&JDM)zBAr3!}zwhqkj56U0b6S>OIgO;64L4`Rq z6s3WGgsiD6SFPLu|J+_#8eTs*C5r!jcV7S=S*IgQNmqV<@8os-oKiVg zNu!z?I;CU-McN(2OQHoi?jJV0Uoeb1o>`x+Y%T#6$D^x1z}CkC@&Yr2!PpxDo}qY!}2v;onFY~ zkr#>RuDa-*qD*LNHSFrUQHbyD^CEwelT9)s#<+i)Ymvf7OlDN7W-dZvq?@7=T}UTv zF*V#VFHs-pW|qSrG}?w}PeDIaKLWq} z{Nhdx2X-`0wsF2WXsSVpbZDG^_6+SteP$HnBMW+TcU9Y{=sV6hXq=4Wd@m>j-^C;U zJ4J^^xsAmMw2{$rpTBPp7VDMZ9<0&)_C7%2}Xs<>^e%VTG1?27gt}?n) zJVqGnT@1c33e*dX`cA#AH>gdj=jB_I?i_IFRM6Enb2Orr!@Khg{Z!xK{Jftg_&xmo zdk}!`))|Y?z)EB4_}syM+s7Qctjn1LYNzt-a?n&f)!uLp-SjG=n_GwR0^nh_m?@}>6;gZ z4C8!vY4E&IX{C04$oEc*l8C=K^?#r#aG#<70V40R5v{5M>%@k$8mjezxI#qyB^DTg zaonL+(7!``C*?`jpJ!9!>pc9j7d0{}-!OcUXGZp^vvfcM!(xCaqN_%+`CQPs4i7mY zXrOG^Tsg49BdLB`d+Xy9Ff7$9Ad~?AiY1%9i%z~0St3x|eWjt+ z)VL1iMN$JCWOhk@ju{sE%=Y zxD?85&2VfmFsP1CXi>ACyriKP8#swZ+m`qfd>Ejjns}3)^kIAPYe1L|Kd|X^PCmag zNJi#Ya5KqF%65_m~O@pq9G#IS;jbSCT zG<*=hw4@OH#580DVUzrAUH$?-Q4!T>SI#5JiOSxGgnp&MeY*?GxqgoE!|xd|Q+-Q^ zdWN(VR>g*9w$LJwF9*h3`EwU<5CBT9yLzlkdsK`n4uDm&fAr7gmRa=CKJXK(#Vy)8 ze?f9VF^NUFOro%06<=~{{Cp*MW6X-j)IjTw3$F5M0%8kpvDI_C)%LH8JF&C(GfWNCCrvpVNOO!G<6Mw!N`u4Vnph}jfZ-ZQxOVO`$MlL(QM95nEx1-)Yp2+M7UHY+oX4y6dk zEUYeum$Ljz*Hwr{xDnQ|h);4?jz9#MA|iN?B z!P90#Xoqi@62=_no`QFpvvfW?4GeIecJxY$WW zlr@6%ZY!}J-*Pe{6`c*#J0jCr3E^&y#7;&$TpbZFhe-}koC@ra7@J;85ugKFa<28U zHNxwD`^xBNK0bJOU~b%jMOFKh(#xWhsCW{Dui@BjDcGQ%21+t1`!NKf#XSxNJLa7V z1JLMTi`+Uvt~X&|xz>KKWQU-H>J^C%qR`>|oZrIR6nHI~Rv!pij@q=icZ}cR8$6{g z{>$1RUEBFHpszt;C6#S$r9WV)MTmz$7qc5>5#ugHcUR(MGR`S{=u^4`%?fuo|PCc(qi&QZ%-6w{?X VRb;t>mIvTJC3$tZ8X2?K{|hy38`S^+ From a47d7b8ee887207fef041f612152711c445addf8 Mon Sep 17 00:00:00 2001 From: dmitrykurmanov Date: Mon, 28 Aug 2023 12:15:56 +0400 Subject: [PATCH 3/8] work for the https://github.com/surveyjs/survey-creator/issues/3340 --- src/dragdrop/dom-adapter.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/dragdrop/dom-adapter.ts b/src/dragdrop/dom-adapter.ts index 17f1518e1b..a2e8e5abe2 100644 --- a/src/dragdrop/dom-adapter.ts +++ b/src/dragdrop/dom-adapter.ts @@ -38,11 +38,8 @@ export class DragDropDOMAdapter implements IDragDropDOMAdapter { private savedTargetNode: any; private scrollIntervalId: number = null; - constructor(private dd: IDragDropEngine, private longTap?: boolean) { - if (typeof longTap === "undefined") { - longTap = true; - } - } + constructor(private dd: IDragDropEngine, private longTap?: boolean) {} + private get rootElement() { if(isShadowDOM(settings.environment.root)) { return settings.environment.root.host; @@ -86,6 +83,11 @@ export class DragDropDOMAdapter implements IDragDropDOMAdapter { document.body.style.setProperty("user-select", "none", "important"); document.body.style.setProperty("-webkit-user-select", "none", "important"); + let longTap = this.longTap; + if (typeof longTap === "undefined") { + longTap = true; + } + this.timeoutID = setTimeout(() => { this.doStartDrag( event, @@ -108,7 +110,7 @@ export class DragDropDOMAdapter implements IDragDropDOMAdapter { } this.stopLongTap(); - }, this.longTap? 500: 0); + }, longTap ? 500: 0); document.addEventListener("pointerup", this.stopLongTap); document.addEventListener("pointermove", this.stopLongTapIfMoveEnough); From f75fe016501d1d8f1b0f93e554156b06a798a4dc Mon Sep 17 00:00:00 2001 From: dmitrykurmanov Date: Mon, 28 Aug 2023 12:23:45 +0400 Subject: [PATCH 4/8] work for the https://github.com/surveyjs/survey-creator/issues/3340 --- src/dragdrop/dom-adapter.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/dragdrop/dom-adapter.ts b/src/dragdrop/dom-adapter.ts index a2e8e5abe2..5b409f3870 100644 --- a/src/dragdrop/dom-adapter.ts +++ b/src/dragdrop/dom-adapter.ts @@ -38,7 +38,7 @@ export class DragDropDOMAdapter implements IDragDropDOMAdapter { private savedTargetNode: any; private scrollIntervalId: number = null; - constructor(private dd: IDragDropEngine, private longTap?: boolean) {} + constructor(private dd: IDragDropEngine, private longTap: boolean = true) {} private get rootElement() { if(isShadowDOM(settings.environment.root)) { @@ -83,11 +83,6 @@ export class DragDropDOMAdapter implements IDragDropDOMAdapter { document.body.style.setProperty("user-select", "none", "important"); document.body.style.setProperty("-webkit-user-select", "none", "important"); - let longTap = this.longTap; - if (typeof longTap === "undefined") { - longTap = true; - } - this.timeoutID = setTimeout(() => { this.doStartDrag( event, @@ -110,7 +105,7 @@ export class DragDropDOMAdapter implements IDragDropDOMAdapter { } this.stopLongTap(); - }, longTap ? 500: 0); + }, this.longTap ? 500: 0); document.addEventListener("pointerup", this.stopLongTap); document.addEventListener("pointermove", this.stopLongTapIfMoveEnough); From bcbebeb0846191d0eb5cb92b7d8f3024d95a744d Mon Sep 17 00:00:00 2001 From: RomanTsukanov Date: Mon, 28 Aug 2023 13:51:09 +0400 Subject: [PATCH 5/8] `SurveyModel`: Update API descriptions (#6801) --- src/survey-events-api.ts | 18 +++++++-------- src/survey.ts | 48 +++++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/survey-events-api.ts b/src/survey-events-api.ts index 208645413d..669a7f1e48 100644 --- a/src/survey-events-api.ts +++ b/src/survey-events-api.ts @@ -397,23 +397,23 @@ export interface GetQuestionNoEvent extends QuestionEventMixin { } export interface ProgressTextEvent { /** - * a number of required questions that have input(s) and an user has answered + * The number of questions with input fields. [Image](https://surveyjs.io/form-library/examples/add-image-and-video-to-survey/), [HTML](https://surveyjs.io/form-library/examples/questiontype-html/), and [Expression](https://surveyjs.io/form-library/examples/questiontype-expression/) questions are not counted. */ - requiredAnsweredQuestionCount: number; + questionCount: number; /** - * a number of required questions that have input(s). We do not count html or expression questions + * The number of answered questions. */ - requiredQuestionCount: number; + answeredQuestionCount: number; /** - * a number of questions that have input(s) and an user has answered + * The number of questions marked as required. */ - answeredQuestionCount: number; + requiredQuestionCount: number; /** - * a number of questions that have input(s). We do not count html or expression questions + * The number of answered questions marked as required. */ - questionCount: number; + requiredAnsweredQuestionCount: number; /** - * a progress text, that SurveyJS will render in progress bar + * Progress text rendered in the [progress bar](#showProgressBar). You can change this parameter's value. */ text: string; } diff --git a/src/survey.ts b/src/survey.ts index d2e1fb575e..6a36734b54 100644 --- a/src/survey.ts +++ b/src/survey.ts @@ -93,7 +93,7 @@ export class SurveyModel extends SurveyElementCore * * Many question types allow respondents to leave comments. To enable this functionality, set a question's [`showCommentArea`](https://surveyjs.io/form-library/documentation/api-reference/checkbox-question-model#showCommentArea) property to `true`. Comment values are saved in a separate property. The property name is composed of the question `name` and `commentSuffix`. * - * Respondents can also leave a comment when they select "Other" in a single- or multi-select question, such as Dropdown or Checkboxes. The property name for the comment value is composed according to the same rules. However, you can use the question `name` as a key to store the comment value instead. Disable the [`storeOthersAsComment`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#storeOthersAsComment) property in this case. + * Respondents can also leave comments when they select "Other" in choice-based questions, such as Dropdown or Checkboxes. The property name for the comment value is composed according to the same rules. However, you can use the question `name` as a key to store the comment value instead. Disable the [`storeOthersAsComment`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#storeOthersAsComment) property in this case. * * [View Demo](https://surveyjs.io/form-library/examples/create-checkboxes-question-in-javascript/ (linkStyle)) */ @@ -398,7 +398,8 @@ export class SurveyModel extends SurveyElementCore */ public onGetQuestionNo: EventBase = this.addEvent(); /** - * Use this event to change the progress text in code. + * An event that is raised before the survey displays progress text. Handle this event to change the progress text in code. + * @see showProgressBar * @see progressBarType */ public onProgressText: EventBase = this.addEvent(); @@ -1461,12 +1462,9 @@ export class SurveyModel extends SurveyElementCore } } /** - * Gets or sets the first question index. The first question index is '1' by default. You may start it from '100' or from 'A', by setting '100' or 'A' to this property. - * You can set the start index to "(1)" or "# A)" or "a)" to render question number as (1), # A) and a) accordingly. - * @see Question.title - * @see requiredText + * Specifies the initial number or letter from which to start question numbering. * - * [View Demo](https://surveyjs.io/form-library/examples/survey-processtext/ (linkStyle)) + * [Question Numbers](https://surveyjs.io/form-library/documentation/design-survey/configure-question-titles#question-numbers (linkStyle)) */ public get questionStartIndex(): string { return this.getPropertyValue("questionStartIndex", ""); @@ -1475,11 +1473,12 @@ export class SurveyModel extends SurveyElementCore this.setPropertyValue("questionStartIndex", val); } /** - * Gets or sets whether the "Others" option text is stored as question comment. + * Specifies whether to store the "Other" option response in a separate property. * - * By default the entered text in the "Others" input in the checkbox/radiogroup/dropdown is stored as `"question name " + "-Comment"`. The value itself is `"question name": "others"`. - * Set this property to `false`, to store the entered text directly in the `"question name"` key. - * @see commentSuffix + * Default value: `true` + * + * Respondents can leave comments when they select "Other" in choice-based questions, such as Dropdown or Checkboxes. Comment values are saved in a separate property. The property name is composed of the question `name` and [`commentSuffix`](#commentSuffix). However, you can use the question `name` as a key to store the comment value instead. Disable the `storeOthersAsComment` property in this case. + * @see maxOthersLength */ public get storeOthersAsComment(): boolean { return this.getPropertyValue("storeOthersAsComment"); @@ -1488,9 +1487,11 @@ export class SurveyModel extends SurveyElementCore this.setPropertyValue("storeOthersAsComment", val); } /** - * Specifies the default maximum length for questions like text and comment, including matrix cell questions. + * Specifies the maximum text length in textual questions ([Single-Line Input](https://surveyjs.io/form-library/examples/text-entry-question/), [Long Text](https://surveyjs.io/form-library/examples/add-open-ended-question-to-a-form/), [Multiple Textboxes](https://surveyjs.io/form-library/examples/multiple-text-box-question/)), measured in characters. + * + * Default value: 0 (unlimited) * - * The default value is `0`, that means that the text and comment have the same max length as the standard HTML input - 524288 characters: https://www.w3schools.com/tags/att_input_maxlength.asp. + * You can override this setting for individual questions if you specify their [`maxLength`](https://surveyjs.io/form-library/documentation/api-reference/text-entry-question-model#maxLength) property. * @see maxOthersLength */ public get maxTextLength(): number { @@ -1500,11 +1501,9 @@ export class SurveyModel extends SurveyElementCore this.setPropertyValue("maxTextLength", val); } /** - * Gets or sets the default maximum length for question comments and others + * Specifies the maximum text length for question comments. Applies to questions with the [`showCommentArea`](https://surveyjs.io/form-library/documentation/api-reference/question#showCommentArea) or [`showOtherItem`](https://surveyjs.io/form-library/documentation/api-reference/question#showOtherItem) property set to `true`. * - * The default value is `0`, that means that the question comments have the same max length as the standard HTML input - 524288 characters: https://www.w3schools.com/tags/att_input_maxlength.asp. - * @see Question.showCommentArea - * @see Question.showOtherItem + * Default value: 0 (unlimited) * @see maxTextLength */ public get maxOthersLength(): number { @@ -2398,9 +2397,9 @@ export class SurveyModel extends SurveyElementCore return options.no; } /** - * Gets or sets whether the survey displays page numbers on pages titles. + * Specifies whether page titles contain page numbers. * - * [View Demo](https://surveyjs.io/form-library/examples/survey-options/ (linkStyle)) + * [View Demo](https://surveyjs.io/form-library/examples/how-to-number-pages-and-questions/ (linkStyle)) */ public get showPageNumbers(): boolean { return this.getPropertyValue("showPageNumbers"); @@ -2548,12 +2547,15 @@ export class SurveyModel extends SurveyElementCore this.setPropertyValue("questionErrorLocation", value.toLowerCase()); } /** - * Gets or sets the question description position. The default value is `underTitle`. + * Specifies where to display question descriptions. * - * The following options are available: + * Possible values: + * + * - `"underTitle"` (default) - Displays descriptions under question titles. + * - `"underInput"` - Displays descriptions under the interactive area. + * + * You can override this setting for individual questions if you specify their [`descriptionLocation`](https://surveyjs.io/form-library/documentation/api-reference/question#descriptionLocation) property. * - * - `underTitle` - show question description under the question title, - * - `underInput` - show question description under the question input instead of question title. */ public get questionDescriptionLocation(): string { return this.getPropertyValue("questionDescriptionLocation"); From 844129e3e111e00d8c41593d69da211dbb81847a Mon Sep 17 00:00:00 2001 From: dmitrykurmanov Date: Mon, 28 Aug 2023 14:00:08 +0400 Subject: [PATCH 6/8] attempt to fix headless CI error ('chromium --headless --no-sandbox --disable-dev-shm-usage') --- package.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index b1c1abea0e..2a074ec6ea 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,11 @@ "test": "karma start ./build-scripts/karma.conf.js", "testcafe": "testcafe chrome testCafe/ --app \"http-server\" --selector-timeout 1500 --reporter minimal", "testcafe_file": "concurrently \"http-server --silent\" \"testcafe chrome testCafe/survey/surveyWidth.ts --selector-timeout 1500 --reporter minimal\"", - "testcafe_ci": "testcafe -c 4 -q chrome:headless testCafe/ --app \"http-server --silent\" --reporter minimal", + "testcafe_ci": "testcafe -c 4 -q 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --app \"http-server --silent\" --reporter minimal", "testcafe_sauce": "testcafe \"saucelabs:Chrome@56.0:Windows 10\" testCafe/", - "testcafe:ko": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --reporter minimal --env=knockout", - "testcafe:react": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --reporter minimal --env=react", - "testcafe:vue": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --reporter minimal --env=vue", + "testcafe:ko": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --reporter minimal --env=knockout", + "testcafe:react": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --reporter minimal --env=react", + "testcafe:vue": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --reporter minimal --env=vue", "release": "commit-and-tag-version --message \"Release: %s [azurepipelines skip]\" ", "build_core_dev": "webpack --config ./build-scripts/survey-core/webpack.config.js --env.buildType dev", "build_core_prod": "webpack --config ./build-scripts/survey-core/webpack.config.js --env.buildType prod", @@ -73,19 +73,19 @@ "test:vue:single": "karma start ./build-scripts/survey-vue/karma.conf.vue.js --single-run", "test:markup": "npm run test:knockout:single && npm run test:react:single && npm run test:vue:single", "visual-regression-tests": "testcafe chrome ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --reporter minimal --selector-timeout 1500", - "visual-regression-tests:ci": "testcafe chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal", - "visual-regression-tests:ci:knockout": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=knockout", - "visual-regression-tests:ci:angular": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=angular", + "visual-regression-tests:ci": "testcafe 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal", + "visual-regression-tests:ci:knockout": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=knockout", + "visual-regression-tests:ci:angular": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=angular", "visual-regression-tests:angular": "testcafe -c 4 -q chrome ./visualRegressionTests/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=angular", - "visual-regression-tests:ci:react": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=react", - "visual-regression-tests:ci:vue": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=vue", - "visual-regression-tests:file": "testcafe chrome:headless --app \"http-server\" ./visualRegressionTests/tests/defaultV2/paneldynamic.ts --screenshots ./ --reporter minimal --selector-timeout 1500", - "visual-regression-tests:ci:vue3": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=vue3", + "visual-regression-tests:ci:react": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=react", + "visual-regression-tests:ci:vue": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=vue", + "visual-regression-tests:file": "testcafe 'chromium --headless --no-sandbox --disable-dev-shm-usage' --app \"http-server\" ./visualRegressionTests/tests/defaultV2/paneldynamic.ts --screenshots ./ --reporter minimal --selector-timeout 1500", + "visual-regression-tests:ci:vue3": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=vue3", "visual-regression-tests:vue3": "testcafe -c 4 -q chrome ./visualRegressionTests/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=vue3", - "testcafe:ci:vue3": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example\" --selector-timeout 1500 --reporter minimal --env=vue3", + "testcafe:ci:vue3": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example\" --selector-timeout 1500 --reporter minimal --env=vue3", "testcafe:vue3": "testcafe chrome testCafe/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example \" --selector-timeout 1500 --reporter minimal --env=vue3", "testcafe:angular": "testcafe chrome testCafe/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --selector-timeout 1500 --reporter minimal --env=angular", - "testcafe:ci:angular": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --selector-timeout 1500 --reporter minimal --env=angular", + "testcafe:ci:angular": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --selector-timeout 1500 --reporter minimal --env=angular", "prepare": "husky install" }, "version": "1.9.104", @@ -195,4 +195,4 @@ "signature_pad": "^4.1.5", "vite": "^3.1.8" } -} +} \ No newline at end of file From f68b61055f0cf8a1f84c18479c9c33c813e9643a Mon Sep 17 00:00:00 2001 From: dmitrykurmanov Date: Mon, 28 Aug 2023 14:48:38 +0400 Subject: [PATCH 7/8] Revert "attempt to fix headless CI error ('chromium --headless --no-sandbox --disable-dev-shm-usage')" This reverts commit 844129e3e111e00d8c41593d69da211dbb81847a. --- package.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 2a074ec6ea..b1c1abea0e 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,11 @@ "test": "karma start ./build-scripts/karma.conf.js", "testcafe": "testcafe chrome testCafe/ --app \"http-server\" --selector-timeout 1500 --reporter minimal", "testcafe_file": "concurrently \"http-server --silent\" \"testcafe chrome testCafe/survey/surveyWidth.ts --selector-timeout 1500 --reporter minimal\"", - "testcafe_ci": "testcafe -c 4 -q 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --app \"http-server --silent\" --reporter minimal", + "testcafe_ci": "testcafe -c 4 -q chrome:headless testCafe/ --app \"http-server --silent\" --reporter minimal", "testcafe_sauce": "testcafe \"saucelabs:Chrome@56.0:Windows 10\" testCafe/", - "testcafe:ko": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --reporter minimal --env=knockout", - "testcafe:react": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --reporter minimal --env=react", - "testcafe:vue": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --reporter minimal --env=vue", + "testcafe:ko": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --reporter minimal --env=knockout", + "testcafe:react": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --reporter minimal --env=react", + "testcafe:vue": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --reporter minimal --env=vue", "release": "commit-and-tag-version --message \"Release: %s [azurepipelines skip]\" ", "build_core_dev": "webpack --config ./build-scripts/survey-core/webpack.config.js --env.buildType dev", "build_core_prod": "webpack --config ./build-scripts/survey-core/webpack.config.js --env.buildType prod", @@ -73,19 +73,19 @@ "test:vue:single": "karma start ./build-scripts/survey-vue/karma.conf.vue.js --single-run", "test:markup": "npm run test:knockout:single && npm run test:react:single && npm run test:vue:single", "visual-regression-tests": "testcafe chrome ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --reporter minimal --selector-timeout 1500", - "visual-regression-tests:ci": "testcafe 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal", - "visual-regression-tests:ci:knockout": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=knockout", - "visual-regression-tests:ci:angular": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=angular", + "visual-regression-tests:ci": "testcafe chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal", + "visual-regression-tests:ci:knockout": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=knockout", + "visual-regression-tests:ci:angular": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=angular", "visual-regression-tests:angular": "testcafe -c 4 -q chrome ./visualRegressionTests/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=angular", - "visual-regression-tests:ci:react": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=react", - "visual-regression-tests:ci:vue": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=vue", - "visual-regression-tests:file": "testcafe 'chromium --headless --no-sandbox --disable-dev-shm-usage' --app \"http-server\" ./visualRegressionTests/tests/defaultV2/paneldynamic.ts --screenshots ./ --reporter minimal --selector-timeout 1500", - "visual-regression-tests:ci:vue3": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' ./visualRegressionTests/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=vue3", + "visual-regression-tests:ci:react": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=react", + "visual-regression-tests:ci:vue": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=vue", + "visual-regression-tests:file": "testcafe chrome:headless --app \"http-server\" ./visualRegressionTests/tests/defaultV2/paneldynamic.ts --screenshots ./ --reporter minimal --selector-timeout 1500", + "visual-regression-tests:ci:vue3": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=vue3", "visual-regression-tests:vue3": "testcafe -c 4 -q chrome ./visualRegressionTests/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=vue3", - "testcafe:ci:vue3": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example\" --selector-timeout 1500 --reporter minimal --env=vue3", + "testcafe:ci:vue3": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example\" --selector-timeout 1500 --reporter minimal --env=vue3", "testcafe:vue3": "testcafe chrome testCafe/ --app \"npm run preview --prefix ./packages/survey-vue3-ui/example \" --selector-timeout 1500 --reporter minimal --env=vue3", "testcafe:angular": "testcafe chrome testCafe/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --selector-timeout 1500 --reporter minimal --env=angular", - "testcafe:ci:angular": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 'chromium --headless --no-sandbox --disable-dev-shm-usage' testCafe/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --selector-timeout 1500 --reporter minimal --env=angular", + "testcafe:ci:angular": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --selector-timeout 1500 --reporter minimal --env=angular", "prepare": "husky install" }, "version": "1.9.104", @@ -195,4 +195,4 @@ "signature_pad": "^4.1.5", "vite": "^3.1.8" } -} \ No newline at end of file +} From cd9747e55557da9523795f4a37aaa4ee0be6221f Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 28 Aug 2023 15:24:45 +0300 Subject: [PATCH 8/8] Rating Question - The getPlainData function result doesn't include a selected rate item and it custom 'score' property value fix #6804 (#6809) --- src/base-interfaces.ts | 8 +++ src/entries/chunks/model.ts | 1 + src/question.ts | 19 ++----- src/question_baseselect.ts | 16 ++---- src/question_file.ts | 12 ++-- src/question_matrix.ts | 12 ++-- src/question_matrixdropdownbase.ts | 15 +---- src/question_paneldynamic.ts | 14 +---- src/question_rating.ts | 8 ++- src/survey.ts | 12 +--- tests/surveytests.ts | 91 +++++++++++++++++++++++++++++- 11 files changed, 133 insertions(+), 75 deletions(-) diff --git a/src/base-interfaces.ts b/src/base-interfaces.ts index e7249462ac..da5d97fb6e 100644 --- a/src/base-interfaces.ts +++ b/src/base-interfaces.ts @@ -369,3 +369,11 @@ export interface ISurveyLayoutElement { template?: string; data?: any; } +export interface IPlainDataOptions { + includeEmpty?: boolean; + includeQuestionTypes?: boolean; + includeValues?: boolean; + calculations?: Array<{ + propertyName: string, + }>; +} \ No newline at end of file diff --git a/src/entries/chunks/model.ts b/src/entries/chunks/model.ts index 336f80eb8c..41811ef991 100644 --- a/src/entries/chunks/model.ts +++ b/src/entries/chunks/model.ts @@ -72,6 +72,7 @@ export { ISurveyData, ITitleOwner, ISurveyLayoutElement, + IPlainDataOptions as IPlainData, IShortcutText } from "../../base-interfaces"; export { SurveyError } from "../../survey-error"; diff --git a/src/question.ts b/src/question.ts index df3e206fb1..d9c59f9bb4 100644 --- a/src/question.ts +++ b/src/question.ts @@ -1,7 +1,7 @@ import { HashTable, Helpers } from "./helpers"; import { JsonObject, Serializer, property } from "./jsonobject"; import { Base, EventBase } from "./base"; -import { IElement, IQuestion, IPanel, IConditionRunner, ISurveyImpl, IPage, ITitleOwner, IProgressInfo, ISurvey } from "./base-interfaces"; +import { IElement, IQuestion, IPanel, IConditionRunner, ISurveyImpl, IPage, ITitleOwner, IProgressInfo, ISurvey, IPlainDataOptions } from "./base-interfaces"; import { SurveyElement } from "./survey-element"; import { surveyLocalization } from "./surveyStrings"; import { AnswerRequiredError, CustomError } from "./error"; @@ -1528,15 +1528,7 @@ export class Question extends SurveyElement * * Pass an object with the `includeEmpty` property set to `false` if you want to skip empty answers. */ - public getPlainData( - options?: { - includeEmpty?: boolean, - includeQuestionTypes?: boolean, - calculations?: Array<{ - propertyName: string, - }>, - } - ): IQuestionPlainData { + public getPlainData(options?: IPlainDataOptions): IQuestionPlainData { if (!options) { options = { includeEmpty: true, includeQuestionTypes: false }; } @@ -1554,9 +1546,7 @@ export class Question extends SurveyElement questionPlainData.questionType = this.getType(); } (options.calculations || []).forEach((calculation) => { - questionPlainData[calculation.propertyName] = this[ - calculation.propertyName - ]; + questionPlainData[calculation.propertyName] = this.getPlainDataCalculatedValue(calculation.propertyName); }); if (this.hasComment) { questionPlainData.isNode = true; @@ -1577,6 +1567,9 @@ export class Question extends SurveyElement } return undefined; } + protected getPlainDataCalculatedValue(propName: string): any { + return this[propName]; + } /** * A correct answer to this question. Specify this property if you want to [create a quiz](https://surveyjs.io/form-library/documentation/design-survey-create-a-quiz). * @see SurveyModel.getCorrectAnswerCount diff --git a/src/question_baseselect.ts b/src/question_baseselect.ts index 4df988dbfe..94a27dfc2a 100644 --- a/src/question_baseselect.ts +++ b/src/question_baseselect.ts @@ -1,8 +1,8 @@ import { property, Serializer } from "./jsonobject"; import { SurveyError } from "./survey-error"; -import { ISurveyImpl, ISurvey, ISurveyData } from "./base-interfaces"; +import { ISurveyImpl, ISurvey, ISurveyData, IPlainDataOptions } from "./base-interfaces"; import { SurveyModel } from "./survey"; -import { Question } from "./question"; +import { IQuestionPlainData, Question } from "./question"; import { ItemValue } from "./itemvalue"; import { surveyLocalization } from "./surveyStrings"; import { OtherEmptyError } from "./error"; @@ -938,17 +938,11 @@ export class QuestionSelectBase extends Question { this.isDesignMode && !this.customWidget && !this.isContentElement; } public getPlainData( - options: { - includeEmpty?: boolean, - includeQuestionTypes?: boolean, - calculations?: Array<{ - propertyName: string, - }>, - } = { + options: IPlainDataOptions = { includeEmpty: true, includeQuestionTypes: false, } - ) { + ): IQuestionPlainData { var questionPlainData = super.getPlainData(options); if (!!questionPlainData) { var values = Array.isArray(this.value) ? this.value : [this.value]; @@ -990,7 +984,7 @@ export class QuestionSelectBase extends Question { protected getDisplayValueEmpty(): string { return ItemValue.getTextOrHtmlByValue(this.visibleChoices, undefined); } - protected getChoicesDisplayValue(items: ItemValue[], val: any): any { + private getChoicesDisplayValue(items: ItemValue[], val: any): any { if (val == this.otherItemValue.value) return this.otherValue ? this.otherValue : this.locOtherText.textOrHtml; const selItem = this.getSingleSelectedItem(); diff --git a/src/question_file.ts b/src/question_file.ts index 89d7fa584a..d236f2b009 100644 --- a/src/question_file.ts +++ b/src/question_file.ts @@ -1,4 +1,5 @@ -import { Question } from "./question"; +import { IPlainDataOptions } from "./base-interfaces"; +import { IQuestionPlainData, Question } from "./question"; import { property, propertyArray, Serializer } from "./jsonobject"; import { QuestionFactory } from "./questionfactory"; import { EventBase, ComputedUpdater } from "./base"; @@ -464,15 +465,10 @@ export class QuestionFileModel extends Question { return result; } public getPlainData( - options: { - includeEmpty?: boolean, - calculations?: Array<{ - propertyName: string, - }>, - } = { + options: IPlainDataOptions = { includeEmpty: true, } - ) { + ): IQuestionPlainData { var questionPlainData = super.getPlainData(options); if (!!questionPlainData && !this.isEmpty()) { questionPlainData.isNode = false; diff --git a/src/question_matrix.ts b/src/question_matrix.ts index e6401e697e..9dec95bbef 100644 --- a/src/question_matrix.ts +++ b/src/question_matrix.ts @@ -9,10 +9,11 @@ import { RequiredInAllRowsError } from "./error"; import { QuestionFactory } from "./questionfactory"; import { LocalizableString, ILocalizableOwner } from "./localizablestring"; import { QuestionDropdownModel } from "./question_dropdown"; -import { IConditionObject } from "./question"; +import { IConditionObject, IQuestionPlainData } from "./question"; import { settings } from "./settings"; import { SurveyModel } from "./survey"; import { CssClassBuilder } from "./utils/cssClassBuilder"; +import { IPlainDataOptions } from "./base-interfaces"; export interface IMatrixData { onMatrixRowChanged(row: MatrixRowModel): void; @@ -484,15 +485,10 @@ export class QuestionMatrixModel return res; } public getPlainData( - options: { - includeEmpty?: boolean, - calculations?: Array<{ - propertyName: string, - }>, - } = { + options: IPlainDataOptions = { includeEmpty: true, } - ) { + ): IQuestionPlainData { var questionPlainData = super.getPlainData(options); if (!!questionPlainData) { var values = this.createValueCopy(); diff --git a/src/question_matrixdropdownbase.ts b/src/question_matrixdropdownbase.ts index 7ac554a5e8..c84938277d 100644 --- a/src/question_matrixdropdownbase.ts +++ b/src/question_matrixdropdownbase.ts @@ -1,9 +1,9 @@ import { JsonObject, CustomPropertiesCollection, Serializer, property } from "./jsonobject"; import { QuestionMatrixBaseModel } from "./martixBase"; -import { Question, IConditionObject } from "./question"; +import { Question, IConditionObject, IQuestionPlainData } from "./question"; import { HashTable, Helpers } from "./helpers"; import { Base } from "./base"; -import { IElement, IQuestion, ISurveyData, ISurvey, ISurveyImpl, ITextProcessor, IProgressInfo, IPanel } from "./base-interfaces"; +import { IElement, IQuestion, ISurveyData, ISurvey, ISurveyImpl, ITextProcessor, IProgressInfo, IPanel, IPlainDataOptions } from "./base-interfaces"; import { SurveyElement } from "./survey-element"; import { TextPreProcessorValue, QuestionTextProcessor } from "./textPreProcessor"; import { ItemValue } from "./itemvalue"; @@ -1732,16 +1732,7 @@ export class QuestionMatrixDropdownModelBase extends QuestionMatrixBaseModel, - } = { - includeEmpty: true, - } - ) { + public getPlainData(options: IPlainDataOptions = { includeEmpty: true }): IQuestionPlainData { var questionPlainData = super.getPlainData(options); if (!!questionPlainData) { questionPlainData.isNode = true; diff --git a/src/question_paneldynamic.ts b/src/question_paneldynamic.ts index b314aba6f7..96372a42fc 100644 --- a/src/question_paneldynamic.ts +++ b/src/question_paneldynamic.ts @@ -8,6 +8,7 @@ import { ISurveyImpl, ITextProcessor, IProgressInfo, + IPlainDataOptions, } from "./base-interfaces"; import { SurveyElement } from "./survey-element"; import { LocalizableString } from "./localizablestring"; @@ -15,7 +16,7 @@ import { TextPreProcessorValue, QuestionTextProcessor, } from "./textPreProcessor"; -import { Question, IConditionObject } from "./question"; +import { Question, IConditionObject, IQuestionPlainData } from "./question"; import { PanelModel } from "./panel"; import { JsonObject, property, Serializer } from "./jsonobject"; import { QuestionFactory } from "./questionfactory"; @@ -1956,16 +1957,7 @@ export class QuestionPanelDynamicModel extends Question getRootData(): ISurveyData { return this.data; } - public getPlainData( - options: { - includeEmpty?: boolean, - calculations?: Array<{ - propertyName: string, - }>, - } = { - includeEmpty: true, - } - ) { + public getPlainData(options: IPlainDataOptions = { includeEmpty: true }): IQuestionPlainData { var questionPlainData = super.getPlainData(options); if (!!questionPlainData) { questionPlainData.isNode = true; diff --git a/src/question_rating.ts b/src/question_rating.ts index 744cfc5e41..8d746bdff0 100644 --- a/src/question_rating.ts +++ b/src/question_rating.ts @@ -7,7 +7,6 @@ import { settings } from "./settings"; import { surveyLocalization } from "./surveyStrings"; import { CssClassBuilder } from "./utils/cssClassBuilder"; import { Base } from "./base"; -import { HtmlConditionItem } from "./expressionItems"; import { mergeValues } from "./utils/utils"; import { DropdownListModel } from "./dropdownListModel"; import { SurveyModel } from "./survey"; @@ -313,6 +312,7 @@ export class QuestionRatingModel extends Question { } protected getDisplayValueCore(keysAsText: boolean, value: any): any { + if(!this.useRateValues) return super.getDisplayValueCore(keysAsText, value); var res = ItemValue.getTextOrHtmlByValue(this.visibleRateValues, value); return !!res ? res : value; } @@ -390,6 +390,12 @@ export class QuestionRatingModel extends Question { public supportOther(): boolean { return false; } + protected getPlainDataCalculatedValue(propName: string): any { + const res = super.getPlainDataCalculatedValue(propName); + if(res !== undefined || !this.useRateValues || this.isEmpty()) return res; + const item = ItemValue.getItemByValue(this.visibleRateValues, this.value); + return item ? item[propName] : undefined; + } /** * Specifies a description for the minimum (first) rate value. * @see rateValues diff --git a/src/survey.ts b/src/survey.ts index 6a36734b54..4b38732fa7 100644 --- a/src/survey.ts +++ b/src/survey.ts @@ -15,6 +15,7 @@ import { IProgressInfo, IFindElement, ISurveyLayoutElement, + IPlainDataOptions, LayoutElementContainer } from "./base-interfaces"; import { SurveyElementCore, SurveyElement } from "./survey-element"; @@ -2754,16 +2755,7 @@ export class SurveyModel extends SurveyElementCore * * If you want to skip empty answers, pass an object with the `includeEmpty` property set to `false`. */ - public getPlainData( - options?: { - includeEmpty?: boolean, - includeQuestionTypes?: boolean, - includeValues?: boolean, - calculations?: Array<{ - propertyName: string, - }>, - } - ): Array { + public getPlainData(options?: IPlainDataOptions): Array { if (!options) { options = { includeEmpty: true, includeQuestionTypes: false, includeValues: false }; } diff --git a/tests/surveytests.ts b/tests/surveytests.ts index 2b41454b36..a5b7126c7b 100644 --- a/tests/surveytests.ts +++ b/tests/surveytests.ts @@ -10188,6 +10188,95 @@ QUnit.test( Serializer.removeProperty("itemvalue", "score"); } ); +QUnit.test("getPlainData - calculate itemvalue.score in rate question, Bug#6804", + function (assert) { + Serializer.addProperty("itemvalue", { name: "score:number" }); + + var survey = new SurveyModel({ + questions: [ + { + type: "rating", + name: "q1", + rateValues: [{ value: 1, score: 2, text: "Score 2" }, { value: 2, score: 4, text: "Score 4" }] + }, + { + type: "dropdown", + name: "q2", + choices: [ + { + value: "item1", + score: 1, + }, + { + value: "item2", + score: 2, + }, + { + value: "item3", + score: 3, + }, + ], + }, + { + type: "checkbox", + name: "q3", + choices: [ + { + value: "item1", + score: 1, + }, + { + value: "item2", + score: 2, + }, + { + value: "item3", + score: 3, + }, + ], + } + ] + }); + survey.data = { + q1: 2, + q2: "item2", + q3: ["item2", "item3"] + }; + const q1 = survey.getQuestionByName("q1"); + const q1PlainData = q1.getPlainData({ calculations: [{ propertyName: "score" }] }); + assert.equal(q1PlainData.displayValue, "Score 4", "display value is correct"); + assert.equal(q1PlainData.isNode, false, "it is not a node"); + assert.equal((q1PlainData).score, 4, "score is correct"); + + const plainData = survey.getPlainData({ + includeEmpty: false, + calculations: [{ propertyName: "score" }], + }); + const calculate = ( + plainData: Array<{ + isNode: boolean, + score?: number, + data?: Array, + }> = [] + ): number => { + return plainData.reduce((result, current) => { + var currentScore = current.score; + if (current.isNode) { + currentScore = calculate(current.data); + } + if (currentScore) { + return result + currentScore; + } + return result; + }, 0); + }; + + const surveyScore = calculate(plainData); + assert.equal(surveyScore, 11, "overall survey score for answered questions"); + + Serializer.removeProperty("itemvalue", "score"); + } +); QUnit.test( "question.getPlainData - select base - multiple select - other", @@ -10219,7 +10308,7 @@ QUnit.test( question.value = ["other", "giraffe"]; question.comment = "Other value text"; - var plainData = question.getPlainData(); + const plainData = question.getPlainData(); assert.deepEqual(plainData.value, ["other", "giraffe"]); assert.equal(plainData.isNode, true); assert.deepEqual(plainData.data.length, 2);