From 48b4ba1fc89964b525a0d2a34843e7f0ea77e094 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Wed, 12 Nov 2008 03:24:49 +0000 Subject: [PATCH] adding survey back in --- docs/changelog/7.x.x.txt | 2 + docs/gotcha.txt | 9 +- .../packages-7.6.4/root_import_survey.wgpkg | Bin 0 -> 8555 bytes docs/upgrades/upgrade_7.6.3-7.6.4.pl | 194 +- lib/WebGUI/Asset/Wobject/Survey.pm | 2274 +++++++---------- .../Asset/Wobject/Survey/ResponseJSON.pm | 338 +++ lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm | 446 ++++ lib/WebGUI/i18n/English/Asset_Survey.pm | 1479 ++--------- www/extras/wobject/Survey/administersurvey.js | 453 ++++ .../wobject/Survey/administersurvey/comm.js | 73 + www/extras/wobject/Survey/bg-fader-500.gif | Bin 0 -> 1197 bytes www/extras/wobject/Survey/bg-fader.gif | Bin 0 -> 433 bytes www/extras/wobject/Survey/dd.js | 125 + www/extras/wobject/Survey/editsurvey.js | 123 + .../wobject/Survey/editsurvey/answer.js | 69 + www/extras/wobject/Survey/editsurvey/comm.js | 75 + .../wobject/Survey/editsurvey/object.js | 32 + .../wobject/Survey/editsurvey/question.html | 40 + .../wobject/Survey/editsurvey/question.js | 112 + .../wobject/Survey/editsurvey/section.js | 28 + www/extras/wobject/Survey/gradient-glossy.png | Bin 0 -> 132 bytes www/extras/wobject/Survey/survey.css | 85 + www/extras/wobject/Survey/surveyedit.css | 132 + www/extras/wobject/Survey/thumb-n.gif | Bin 0 -> 612 bytes 24 files changed, 3463 insertions(+), 2626 deletions(-) create mode 100644 docs/upgrades/packages-7.6.4/root_import_survey.wgpkg create mode 100644 lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm create mode 100644 lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm create mode 100644 www/extras/wobject/Survey/administersurvey.js create mode 100644 www/extras/wobject/Survey/administersurvey/comm.js create mode 100644 www/extras/wobject/Survey/bg-fader-500.gif create mode 100644 www/extras/wobject/Survey/bg-fader.gif create mode 100644 www/extras/wobject/Survey/dd.js create mode 100644 www/extras/wobject/Survey/editsurvey.js create mode 100644 www/extras/wobject/Survey/editsurvey/answer.js create mode 100644 www/extras/wobject/Survey/editsurvey/comm.js create mode 100644 www/extras/wobject/Survey/editsurvey/object.js create mode 100644 www/extras/wobject/Survey/editsurvey/question.html create mode 100644 www/extras/wobject/Survey/editsurvey/question.js create mode 100644 www/extras/wobject/Survey/editsurvey/section.js create mode 100755 www/extras/wobject/Survey/gradient-glossy.png create mode 100644 www/extras/wobject/Survey/survey.css create mode 100644 www/extras/wobject/Survey/surveyedit.css create mode 100644 www/extras/wobject/Survey/thumb-n.gif diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 024fac5be..cedcafbc6 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -1,4 +1,6 @@ 7.6.4 + - Brand new Survey system. Make sure to export your old results as they will + not be imported, only the surveys themselves. 7.6.3 - improved performance of file uploads diff --git a/docs/gotcha.txt b/docs/gotcha.txt index e7a61db9e..940b99a09 100644 --- a/docs/gotcha.txt +++ b/docs/gotcha.txt @@ -7,6 +7,14 @@ upgrading from one version to the next, or even between multiple versions. Be sure to heed the warnings contained herein as they will save you many hours of grief. +7.6.4 +-------------------------------------------------------------------- + * The Survey system has been completely updated. Please make sure you + create full backups of your survey results and export them as needed. + Results will not be imported into the new Survey system. Your old surveys + will be imported into the new survey system. + + 7.6.3 -------------------------------------------------------------------- * WebGUI now requires XML::FeedPP version 0.36 or greater. @@ -19,7 +27,6 @@ save you many hours of grief. * You must upgrade to 7.6.2 before you can upgrade to 7.6.3. - 7.6.1 -------------------------------------------------------------------- * WebGUI now requires Class::C3 version 0.19 or greater. diff --git a/docs/upgrades/packages-7.6.4/root_import_survey.wgpkg b/docs/upgrades/packages-7.6.4/root_import_survey.wgpkg new file mode 100644 index 0000000000000000000000000000000000000000..ebdf80a214f2a59ccc5c51c75bddfdd40dfdf11e GIT binary patch literal 8555 zcmV-xA(Y-9iwFP!00000|Lt9QciTpi_uum=Fq)TP=DneK>$0qUvTP^L$dYW!v6I!V z9!NkUY!ILUP)D-)?psxT0u6xRAv&?CyqF~VsOswK?y6r`H#Q$V{9m)#-0t-rJ;Ki| z_StNAA3d_mYhrv==gxa^d(BJTx*Z=LUPAk*@oi04GK$;K#_fY-6 z`S7eSgTn8BgF(0vCt+k?yBpS?_22*VZ+bM2!m%4Ao*Uy+%7!@|FCP2${kfO;lzpSM zLHRLl5V>~ZI#2Jh#70LY_;#E;zZ-`Uq#jaz!Nm7vIT%_At86^!`(8YB9aT1PZ{K@? z6W&s#O_dPe!+?!Fv%2s$aHDsz8@+V0jJS76WdG>e&bfVU7PRBoO?aVRKREdC5ee%YU}C`n+K1MqctR@?S*Z=**7XfK{yJaol(idE>+jsXb=j z9u4i_I#)5gz~y?kLF7|2k>Y#+8Wf+{BPNvhZvTgOFZcEivA_2A-iQ5johZL31@CvSWbCQ$Rh7R}z! zBr zdi}@Y`}5PC|Fl0lH^2UL`#~FIUi|hx2Ey4j2YIV1_y6x_cHpz`?2*}Yx-6cm3ebGkTIP!u7NxiK;^lwksrTR6+C>;KoZ#^B}2CvS__J*l)nYivSWS z!Mn01VDM}X>;RXmH^g5I8TM)Ru?DX1$76fo1=mk5Hrf{(^ki&14tvsqCuAK!YClAi zWiJkW&#_|9helhi@!jK#4XQ6fvdMnpSc4Gj44_Dt(k>Ewjp95~5@0$1juV?g zo@&MNtbSG((8qZbDxwPaI-TzxCt$Tuwo#qTAssY7kR0CTpH5R0CB{2z_y7aLFy% zw1fE8jdB{1NzY;bLHPMRabq+ri#bv`R>f0ES92+;9IN7K5Q6IkevxacALmKsFnAJ* zB~=a{;56%9q51{;{m5#-H}MJIn4e>zdj?YqYG31{ePgr7FwwzE;YN@`pKQYXd%b=U zTup)jcBhqu*Vn%L%)9yC@oru^|FV9+2*BQh`TKh(98AD(NH(wCzqj0^x`+Ri-R-GdVeI6JnsIz?706`=q(qPbs9Dr~LU!j((oh|Lh2LW$%mpbvjmvYja@ zM#bg;)~IBm8UT^OMNhATD=}LzQF}?ej9VpKl?mjVO z!$istMT{g+QPPFvuhb9%gMb!ELyX2UYUGd$3zOO`1-Ov1McBx;V9^S1kHQg-FUd9M zQW^{YfUz6~1K%5bLPerM`+W_j5-g?c1R+T0p!P4aHb^>XrNzVW7C5K;vFxs_`JhiX zOjc?k6taf?k}6-wdt`YIFj~T()`!$s&3fx((xejc>e5<7T{<@Vi)RL@v*C>SfD&t> z9OUw;GNLGxSpH=RHV5a{0Cg%8A*+vavc{rQ`cn){)uB?-UO|_#9@l#mr!FAH*9!U$ zQ#}n&##{p7}!r@_Qz+5}MwhrOh z5qQ?bT?Tg+V%^*O@%+`X_@!Df1mof(h1Qk;xn9hhV#otGNqCo0S|x;+1DLHU z2rsT#FM}6hG-BAa24n;Py`uxqdWqrL4bk7K#g#zcaUb*qacI(E{*Okh2=pcRdI^wj zyW83AZS8I;wo{O9!N$*OQQ3uIy~-7^iA4R|*`@F8)#1O^*7kPCz<--tYy7uzCoYh2 zjsNl)h<|KpQ-2o!m5AX=0pK2HrJx0y60W{m~qG9sgMx94-9N zHT(18tIY~!NMS2b;2Xg*l;_{1*h}vJcUI{CL$Fsb>;E^myKDb{ z0k^(#(Y61d@&7d>GVA|mVMk=sc1B)s8XRB-vN7~6ra>4a5yW;uHL#V3Rj7T+Y^C~f099LIz}l3` zR2;dgOKz!ZQRXUjj1d~SwWivRcJ(C$$KhrJL$75OqWOHUP|4bbyqB!YFVVZO4*vHg z#+$KyDck?PhB+*jqxSC_MWbJ`+F?7GS*t|?MDE1@vWEnh=k_O8<8mK5$KWo3JmuVB zjybtAI7$T-BI`*mQ(ACjTp%;dVzKzTcov~yH>t(B%Bh438)%v-u@bv8by6dd2M@&N z73*`=$`$ULWl7IqW1`uhc>ba`rpAZ9!&!a1jGYfjbF4W@KfQZD z`A>3Gf7ZP3{_@*-g`*McU9!ri&pIPWpuqm`uF(G9YPGZHKf6uX5?r7ET!DtJ?f;DZ zuSH5^?SFwXs;T@zJ%BPR+OTeoqaR?Uk!dSq;FM(>(?LfQbLGzk{%jvuNCs>9XCKb% zJ{G@(HJWp%LT*VJcsxH-Au}vOMQ+5JZ74aqL9I#qGI=fG#}QRWf)FIc3`F@aJYAqrSZK7=!H~tv>P~OBxJHd08^${?@S^V zd&kA`?bVtHo*n ziiA?6%|xwnqB*Rjt{5UxI)?>O2$Zk7RuuJ=tPH=X25|CnWYVry4&$lfRD-@fCOcoW zrc?^)p4J);3AFht=Ta>qSX*Y76ECYR?W=M3Tbe^^y8CbV(K*%56*~MT@mXB{-5qVq z?yGS5^{!f$%il1CT*>!;`tj~f(@DJOuK7djuIE3y39qhRD>Ye1$gaRK`bJ0;`2W4t z`Tu|)w$1q8*82X3m1y9%?EnAp=H1DQLE<~_uETNt^PA&Ic=_y5&9lP)H}80AIPA|)+zC?U9uyTAxe2)RNiwdxpC{f8xClqEUkAq$>*sJP89fK~6MY9fpFB)P{$pz} z#MqDI$t1a|?|^a7d||Rl4%o34i){f|bgvGWWw<**mL-|Rc$S6vIb@HgPCyUhSaTQp zp>uEjZjI~+j&SWYA43cj-7mXHq|QwrSw<-(a$lZLp;p#klR z?6`41@f!V!=R1unXmiZ|t%Fy(Ni2!2!6noW$370a4;!=f9+8NpDvwLf086& zU=m}`mrf3~#fGD1kx5Y|EuE+j2Ws;uvgb=8cgwB?YcRd$m$TtOT~hr@`@j=~`?^d4 zvgavsH~{qjr`{+KM*|oarp8YayafPm=WEDsuw-MjtUPcJq~@;v-X4Zw-3do^_Xg&c zM&|c2Nl7(p$ZwYr!09fN28~}Du1k~=AE|s`F0o>eLjcF}Ay@-N!oOz3!6xu&_fZsS zkCe2Md8U4vspqX8ZxC(ZKg+C?k23aAhnwH*oZ1&+n@>yZgVqtVQ^nw&ab#sCBge_% zeX%NWX5#?9$@Q|T26Y*Y9+340o3nE$P{%f;8A3nF)DS?a1@mzo*XBAb&DaioeNbJBbvaBbqVcr3uJ z>DC?%z;)naRk+g>FVWaMf&#lRZ2% zl3(-NgNo7*>9(U(Dhu;QG7`-c*c=g8=_n$)Z2~op3z|oX%cfz^9B2mda_~DXlzBz? zop$9X8N?Jxk`C9go`V=vQ&$M#af3Zge+Cq! z3p~&$yZ^P>?Bw8o?REUmDpcxQ#{Zn1kFQ?6dIRRv>+R(Btn0Uaef#oOt>xA6Ka90j z<-ThCZwYAH8m*fb=Tv^X0Y=KC6yCJIgzkb1)*)`l&O-=!N{S@83v-jrILh3k)$v^B z3*o)MCPK_SA-r-EToHyu<2UrtI3R7owZQy|c5g65jlruc_V8c=eAe&t^3XAIz-0EU z=J*c(r%VKC(?6T&oWfnnzl-`={D`&FgeVx*`4859 zRVQmjHZRs9s9{VHP^02_11Ee3FA>E>-`Q{JNAIV6=o}YXb4CH4$19-dx=c8d0*8Y# zZl4H&DmurKI!1&%&j?E>#5Ds)R)8lLA}1l%Qm}O)5(pDG@XD2j_)>sBEks1l5eoLZ zEPz@UqEiO9E>!U}$aSI0K|0l7*F~xD4HwxPIdIoPB+B5|g({XSf%sCQq+-gOdyL0$ z|2%9Gv5x{ma}vocGISaeAUe2~jv}LrP|i7IH-%D8&tsEBv&3g=5@yQ`0B`>c`tevz z!Ni>e=U7V!bQItwW)Od(W}Vu;7mOzfTU3Yib|OL>@g+NFb~41M%Zd9$1rlO}v|LlL zVo{m+gb3RQ!2z|a`&NSkwl#`{I3S+dR6fA!alkbFnQ%b;EkR!e4ybq7(s01EfGgpE zr`tE3!7s1-!|~wh?)B@_EvNJOOp7pi;7C4>18%Qzz*Rsge@Pkz_}}*G@V|Da-Py|C z|Ivc?gRam2tw5u`W&H2x?$!AD<-0R`^6Oz|yz|kCP7j~XhX09U5V2bM9~AwQ_MNl> zg(Zgu7}<%iH_H;qQqhjV(0w8`dRo(5cPxm1nZgibXO@MBdQoM3A{U~9niNV+nuq&W zaIG}E(WJ&qQ@m%o1}|BNC;gF^K#Wu5CX*Q})3cc{iV_pEa0k*={J{YqR_BP{QGYZHy@AV^ zz^wSks#aO;yH^nCbQTX2upUX>Nvq^ zMi4cWcUEDw<5;3NR7fl)~oI<5H)pf7jK5A<7oF9YzE8n^pru-)pEKECaC2 zW*swAcG}751f3bxBKB6T63K~TOW}XInB~$@)|Hf3|*kk2le34;U(qRX3XM4Axm z6tTf9!VaVep=3XGHABN`N`2Ihi~)k0RjyGLxZtlHW44c)U8c%(O7lc>bzMMyrP)wq z?@AW(7gg#8nWu`9Oz8%xMWz8F+faCRK4+blg{ZR%#|+&(T`-oIR!(291u6X8PlnTl zF^~QfSIZ48&B{h?fe}5zkjVugx_uc_DnafHp0`Q@Z~`JWJ;i zPm6qRyk=;n?g$br@wrKIsbdliz#{Z(L)bFN7FK90COMF&XeOfyIp&pXuFE}i0c=Q- zVNvams~@AEXO`pw0JIv`*p?_V4V=;lO!c9lQVz^;!?Mt=NL%{lD=<+y;7uZY0&oI) zDKU+#;zp`!3&xAmKXbXxN)0M2!wXO>qBm5v_(VQUx0&tqrwy*mD&kCR|1HG@uxz3x z*#%UiTG?xMD_x(=XilU>22%lU#8rctt4%{8c#CrvZ`LTC%l1mRG<_993v(>vEcb?- z2~sV^;1GCCO$DZiDtA^XfQxti*AANH3Z35%d;-Gxhi0M*EEe@t1s1d8he5UK1eefF z{LFShCJngFn=-{IvL=OwJZAqEH?C}A+5Rko za%qfGgVinzu7@1X)v4){tGs(53YoKL;cym3@bmxp(AQQuvJB>0<5-~CV_s*rY1|gc z$O5V1m?6_&=S=^etx8Xm&17HlX1i2&ek!-x%$F)zVPGyi3(iU~Z<3>D#;DV4*1zx1 zG`W@a1lFoHdUYCk->2uya|p_ZzfK3#A>}aXY2v$P3gk5`yAJ2ru~-vOLZ_E32mGy9 z#nUurF8xI0WuzojZTo(Bdjv=5;V7oE_(WzRIzHg(djL7XAX1w*S^tOc-SGPtYiy6k z%*50AE=|p1yEKLQ_&yDeT|pkcDgerCC$i68p}D3uAMa|OZWud z*Fp!x3*Hm17{K66@hN^9}g5_Ggn7tJtKap+$QMOk4G zY7X@oLQr=)T}=RAMF^_iSzj^)^>ggjcdp})?%0oSKHR^sqx}+*auPPh+t{uA;*qv}fm6x=<0BtO~ z>Ob#QT*Bhg>+VC{Xk3x4s>O8T*O~=)Qw~FjvphR}dtS3_3R`?q`>(4>FyMyYY5yZg z3~yB7d@E~SfLF5mvC#^_cmNO(#2FgzT+?nj=P#ynol6MflT~UaX)PUF2B951qC+!{ zG5)W-Fgn!i#Sj7}7QeER^c=N!&hBN%v$?!?1$09^p`i2oxI8E_It)LyGL*h3p+fI9g z#XR;wG=rga9l~X6vWlfLid73Hi45(AO=VDqkX!I}Z+uI4j_8E)?z0GN9xfwGp1IK( zmXia8v`In+YH09`seF_-9OGSaIkOIe?a(L*9xw)6hsT1u&XbmM!?j>2AH%851&QbogAsfGbM7tcTC#9IdOhifNbMtr6gFqxnGEp;35X<%nQ6*!IQxWST^x@8$9e zE)f-}s1+jn11m(9%meE}mfTX+AY1uLHNXNl-qeEBx_~a?2%{@?1Y z@&83|{i}Cajf)41B3V#@NX0?5d|7~rU|JWnv@ku zN3I}_hcFUAUoFj2JcJ|R(%s3iS*7qF2DKHn3glM&t_Uwnz}@2EnZ+_GckpFJhx9^> zSh;l4Im~8R*{(x|rJ_9tp3Puu)*XjwqYyWVip89dk*AL)F_F@#2cce=L8>8fP=tw- z?v_E~9N@-1AVcFbcsS20gVl(zj)fPO&gUM zsEDWaExx%~+#l2eeGW?PY>9gKss9|Ur@KJ3iveneel2;kt$?MB)=y_^R<)ONr#b85 zxe}T)VUe`>=`CZ&S(GmqIBKuFqCnz^a*olHA6n2lEz$8ADeGAbc9tk$iiQPXgN4J+ zDcV#>ttnbP*=Wm>by%lWAX+_(!OpCrC7qM!j<_7p?8qMBHBVz6w$DxiSQyv4r|*Se zFZ1=*M7nroSV*kV`XdXYiT8Bf&+31b+Od*M?eqxt^YN}NIyxX|9^jH-(p^>KYGBe{ zQ&BWw(%1a;a9<85E#P1VptQ4-YeEo1Ozw(A{78Tdy+$4;G*?^H1u*EaY^57|G4z412Ma4Cx;i z5S0jeE)i0g(<3Y$lZ zp_uSE;cEr(0DRiH=-3z}PJ2>NLj^kUf}`;~gs_~Tgx@QW0yvl5cs-}`$?_&1B9e?y zWUh)iEtGM{MwtbaQ}9usn#~}a! literal 0 HcmV?d00001 diff --git a/docs/upgrades/upgrade_7.6.3-7.6.4.pl b/docs/upgrades/upgrade_7.6.3-7.6.4.pl index 8a645aefc..5be965c21 100644 --- a/docs/upgrades/upgrade_7.6.3-7.6.4.pl +++ b/docs/upgrades/upgrade_7.6.3-7.6.4.pl @@ -28,20 +28,196 @@ my $quiet; # this line required my $session = start(); # this line required -# upgrade functions go here +migrateSurvey($session); finish($session); # this line required -#---------------------------------------------------------------------------- -# Describe what our function does -#sub exampleFunction { -# my $session = shift; -# print "\tWe're doing some stuff here that you should know about... " unless $quiet; -# # and here's our code -# print "DONE!\n" unless $quiet; -#} +#---------------------------------------------------------------------------- +# This method migrates the the old survey system and existing surveys to the new survey system +# +# +sub migrateSurvey{ + my $session = shift; + print "Migrating surveys to new survey system..." unless $quiet; + + _moveOldSurveyTables($session); + _addSurveyTables($session); + + print "\n"; + + my $surveys = $session->db->buildArrayRefOfHashRefs( + "SELECT * FROM Survey_old s + where s.revisionDate = (select max(s1.revisionDate) from Survey_old s1 where s1.assetId = s.assetId)" + ); + + for my $survey(@$surveys){ + + #move over survey + $session->db->write("insert into Survey + values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + [ + $$survey{groupToTakeSurvey},$$survey{groupToViewReports},'PBtmpl0000000000000064','PBtmpl0000000000000063',$$survey{maxResponsesPerUser}, + $$survey{gradebookTemplateId},$$survey{assetId},'PBtmpl0000000000000061',$$survey{revisionDate},'GRUNFctldUgop-qRLuo_DA','AjhlNO3wZvN5k4i4qioWcg', + 'wAc4azJViVTpo-2NYOXWvg', '1oBRscNIcFOI-pETrCOspA','d8jMMMRddSQ7twP4l1ZSIw','CxMpE_UPauZA3p8jdrOABw','','{}' + ] + ); + + my $sjson = WebGUI::Asset::Wobject::Survey::SurveyJSON->new(); + + #move over sections + my $sql = "select * from Survey_section_old where Survey_id = '$$survey{Survey_id}' order by sequenceNumber"; + my $sections = $session->db->buildArrayRefOfHashRefs($sql); + my $sId = 0; + my %sMap; + for my $section(@$sections){ + my $random = $$section{questionOrder} eq 'random' ? 1 : 0; + $sMap{$$section{Survey_sectionId}} = $sId; + $sjson->update([$sId++], + { + 'text','','title',$$section{sectionName},'variable',$$section{Survey_sectionId}, + 'questionsPerPage',$$survey{questionsPerPage},'randomizeQuestions',$random + } + ); + } + + #move over questions + #my %qMap = ('radioList','Multiple Choice','text','Text','HTMLArea','Text','textArea','Text'); + $sql = "select * from Survey_question_old where Survey_id = '$$survey{Survey_id}' order by sequenceNumber"; + my $questions = $session->db->buildArrayRefOfHashRefs($sql); + my $qId = 0; + my %qMap; + my %qS; + for my $question(@$questions){ + $qMap{$$question{Survey_questionId}} = $qId; + $qS{$$question{Survey_questionId}} = $$question{Survey_sectionId}; + $sjson->update([$sMap{$$question{Survey_sectionId}},$qId++], + { + 'text',$$question{question},'variable',$$question{Survey_questionId},'allowComment',$$question{allowComment}, + 'randomizeAnswers',$$question{randomizeAnswers},'questionType',$qMap{$$question{answerField}} + } + ); + } + + + #move over answers + $sql = "select * from Survey_answer_old where Survey_id = '$$survey{Survey_id}' order by sequenceNumber"; + my $answers = $session->db->buildArrayRefOfHashRefs($sql); + my $aId = 0; + my %aMap; + for my $answer(@$answers){ + $aMap{$$survey{Survey_answerId}} = $aId; + $sjson->update([$sMap{$qS{$$answer{Survey_questionId}}},$qMap{$$answer{Survey_questionId}},$aId++], + { + 'text',$$answer{answer},'goto',$$answer{Survey_questionId},'recordedAnswer',$$answer{answer}, + 'isCorrect',$$answer{isCorrect},'NEED TO MAP QUESTION TYPES' + } + ); + } + my $date = $session->db->quickScalar('select max(revisionDate) from Survey where assetId = ?',[$$survey{assetId}]); + $session->db->write('update Survey set surveyJSON = ? where assetId = ? and revisionDate = ?',[$sjson->freeze,$$survey{assetId},$date]); + + + my $rjson = WebGUI::Asset::Wobject::Survey::ResponseJSON->new(undef,undef,$sjson); + $rjson->createSurveyOrder(); + #move over responses + $sql = "select * from Survey_response_old where Survey_id = '$$survey{Survey_id}'"; + my $responses = $session->db->buildArrayRefOfHashRefs($sql); + for my $response(@$responses){ + $session->db->write('insert into Survey_response values(?,?,?,?,?,?,?,?,?,?)', + [ + $$survey{assetId},$$response{Survey_responseId},$$response{userId},$$response{userName},$$response{ipAddress},$$response{startDate},$$response{endDate}, + $$response{isComplete},undef,'{}' + ] + ); + #$sql = "select * from Survey_questionResponse_old where Survey_responseId = '$$response{Survey_responseId}'"; + #my $qresponses = $session->db->buildArrayRefOfHashRefs($sql); + #for my $qresponse(@$qresponses){ + #} + } + } + + print "Finished\n" unless $quiet; +} + + +sub _moveOldSurveyTables{ + my $session = shift; + eval{ + $session->db->write("alter table Survey rename to Survey_old"); + $session->db->write("alter table Survey_answer rename to Survey_answer_old"); + $session->db->write("alter table Survey_question rename to Survey_question_old"); + $session->db->write("alter table Survey_section rename to Survey_section_old"); + $session->db->write("alter table Survey_response rename to Survey_response_old"); + $session->db->write("alter table Survey_questionResponse rename to Survey_questionResponse_old"); + }; +} + +sub _addSurveyTables{ + my $session = shift; + $session->db->write("DROP TABLE IF EXISTS `Survey`"); + $session->db->write(" +CREATE TABLE `Survey` ( + `groupToTakeSurvey` char(22) character set utf8 collate utf8_bin NOT NULL default '2', + `groupToViewReports` char(22) character set utf8 collate utf8_bin NOT NULL default '3', + `responseTemplateId` char(22) character set utf8 collate utf8_bin NOT NULL, + `overviewTemplateId` char(22) character set utf8 collate utf8_bin NOT NULL, + `maxResponsesPerUser` int(11) NOT NULL default '1', + `gradebookTemplateId` char(22) character set utf8 collate utf8_bin NOT NULL, + `assetId` char(22) character set utf8 collate utf8_bin NOT NULL, + `templateId` char(22) character set utf8 collate utf8_bin NOT NULL, + `revisionDate` bigint(20) NOT NULL default '0', + `surveyEditTemplateId` char(22) default NULL, + `answerEditTemplateId` char(22) default NULL, + `questionEditTemplateId` char(22) default NULL, + `sectionEditTemplateId` char(22) default NULL, + `surveyTakeTemplateId` char(22) default NULL, + `surveyQuestionsId` char(22) default NULL, + `exitURL` varchar(512) default NULL, + `surveyJSON` longblob, + PRIMARY KEY (`assetId`,`revisionDate`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +"); + $session->db->write("DROP TABLE IF EXISTS `Survey_response`"); + $session->db->write(" +CREATE TABLE `Survey_response` ( + `assetId` char(22) character set utf8 collate utf8_bin NOT NULL, + `Survey_responseId` char(22) character set utf8 collate utf8_bin NOT NULL, + `userId` char(22) default NULL, + `username` char(255) default NULL, + `ipAddress` char(15) default NULL, + `startDate` bigint(20) NOT NULL default '0', + `endDate` bigint(20) NOT NULL default '0', + `isComplete` int(11) NOT NULL default '0', + `anonId` varchar(255) default NULL, + `responseJSON` longblob, + PRIMARY KEY (`Survey_responseId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + "); + $session->db->write("DROP TABLE IF EXISTS `Survey_tempReport`"); + $session->db->write(" +CREATE TABLE `Survey_tempReport` ( + `assetId` char(22) NOT NULL, + `Survey_responseId` char(22) NOT NULL, + `order` smallint(5) unsigned NOT NULL, + `sectionNumber` smallint(5) unsigned NOT NULL, + `sectionName` varchar(512) default NULL, + `questionNumber` smallint(5) unsigned NOT NULL, + `questionName` varchar(512) default NULL, + `questionComment` mediumtext, + `answerNumber` smallint(5) unsigned default NULL, + `answerValue` mediumtext, + `answerComment` mediumtext, + `entryDate` bigint(20) unsigned NOT NULL COMMENT 'UTC Unix Time', + `isCorrect` tinyint(3) unsigned default NULL, + `value` int(11) default NULL, + `fileStoreageId` char(22) default NULL COMMENT 'Not implemented yet', + PRIMARY KEY (`assetId`,`Survey_responseId`,`order`), + KEY `assetId` (`assetId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + "); +} # -------------- DO NOT EDIT BELOW THIS LINE -------------------------------- diff --git a/lib/WebGUI/Asset/Wobject/Survey.pm b/lib/WebGUI/Asset/Wobject/Survey.pm index f9f64f7be..036c88a05 100644 --- a/lib/WebGUI/Asset/Wobject/Survey.pm +++ b/lib/WebGUI/Asset/Wobject/Survey.pm @@ -11,554 +11,497 @@ package WebGUI::Asset::Wobject::Survey; #------------------------------------------------------------------- use strict; -use List::Util; -use Tie::CPHash; -use WebGUI::HTMLForm; +use Tie::IxHash; +use JSON; use WebGUI::International; -use WebGUI::SQL; -use WebGUI::Utility; -use WebGUI::Asset::Wobject; -use Digest::MD5 qw(md5_hex); +use WebGUI::Form::File; +use base 'WebGUI::Asset::Wobject'; +use WebGUI::Asset::Wobject::Survey::SurveyJSON; +use WebGUI::Asset::Wobject::Survey::ResponseJSON; -our @ISA = qw(WebGUI::Asset::Wobject); - -#------------------------------------------------------------------- -sub addAnswer { - my $self = shift; - my $answer = shift; - my $qid = shift; - my $i18n = WebGUI::International->new($self->session,'Asset_Survey'); - $self->setCollateral("Survey_answer","Survey_answerId",{ - Survey_id=>$self->get("Survey_id"), - Survey_questionId=>$qid, - Survey_answerId=>"new", - answer=>$i18n->get($answer) - },1,0,"Survey_id"); -} - -#------------------------------------------------------------------- -sub addSection { - my $self = shift; - my $sectionName = shift; - my $sectionId = $self->setCollateral("Survey_section","Survey_sectionId",{ - Survey_id=>$self->get("Survey_id"), - Survey_sectionId=>"new", - sectionName=>$sectionName - },1,0,"Survey_id"); - - return $sectionId; -} - -#------------------------------------------------------------------- -sub completeResponse { - my $self = shift; - my $responseId = shift; - $self->session->db->setRow("Survey_response","Survey_responseId",{ - 'Survey_responseId'=>$responseId, - isComplete=>1 - }); - $self->session->scratch->delete($self->getResponseIdString); -} +use Data::Dumper; +# #------------------------------------------------------------------- sub definition { - my $class = shift; - my $session = shift; - my $definition = shift; - my $i18n = WebGUI::International->new($session,'Asset_Survey'); - push(@{$definition}, { - assetName=>$i18n->get('assetName'), - uiLevel => 5, - icon=>'survey.gif', - tableName => 'Survey', - className => 'WebGUI::Asset::Wobject::Survey', - properties => { - templateId => { - fieldType => 'template', - defaultValue => 'PBtmpl0000000000000061' - }, - Survey_id => { - fieldType => 'text', - defaultValue => undef - }, - questionOrder => { - fieldType => 'text', - defaultValue => 'sequential' - }, - groupToTakeSurvey => { - fieldType => 'group', - defaultValue => 2 - }, - groupToViewReports => { - fieldType => 'group', - defaultValue => 4 - }, - mode => { - fieldType => 'text', - defaultValue => 'survey' - }, - anonymous=>{ - fieldType => 'yesNo', - defaultValue => 0 - }, - maxResponsesPerUser=>{ - fieldType => 'integer', - defaultValue => 1 - }, - questionsPerResponse=>{ - fieldType => 'integer', - defaultValue =>99999 - }, - questionsPerPage=>{ - fieldType => 'integer', - defaultValue => 1 - }, - overviewTemplateId=>{ - fieldType => 'template', - defaultValue => 'PBtmpl0000000000000063' - }, - gradebookTemplateId => { - fieldType => 'template', - defaultValue => 'PBtmpl0000000000000062' - }, - responseTemplateId => { - fieldType => 'template', - defaultValue => 'PBtmpl0000000000000064' - }, - defaultSectionId => { - fieldType => 'text', - defaultValue => 'undef' - }, - } - }); + my $class = shift; + my $session = shift; + my $definition = shift; + my $i18n = WebGUI::International->new($session,'Asset_Survey'); + my %properties; + tie %properties, 'Tie::IxHash'; + %properties = ( + templateId =>{ + fieldType=>"template", + defaultValue=>'PBtmpl0000000000000061', + tab=>"display", + namespace=>"Survey", + hoverHelp=>"A Survey System", + label=>"Template ID" + }, + groupToEditSurvey => { + fieldType => 'group', + defaultValue => 4, + label => "Group to edit survey", + }, + groupToTakeSurvey => { + fieldType => 'group', + defaultValue => 2, + label => "Group to take survey", + }, + groupToViewReports => { + fieldType => 'group', + defaultValue => 4, + label => "Group to view reports", + }, + exitURL => { + fieldType => 'text', + defaultValue => undef, + label => "Set the URL that the survey will exit to", + hoverHelp=>"When the user finishes the survey, they will be sent to this URL. Leave blank if no forwarding required.", + }, + maxResponsesPerUser=>{ + fieldType => 'integer', + defaultValue => 1, + label => "Max user reponses", + }, + overviewTemplateId=>{ + tab => 'display', + fieldType => 'template', + defaultValue => 'PBtmpl0000000000000063', + label => "Overview template id", + namespace => 'Survey/Overview', + }, + gradebookTemplateId => { + tab => 'display', + fieldType => 'template', + label => "Grabebook template id", + defaultValue => 'PBtmpl0000000000000062', + namespace => 'Survey/Gradebook', + }, + responseTemplateId => { + tab => 'display', + fieldType => 'template', + label => "Response template id", + defaultValue => 'PBtmpl0000000000000064', + namespace => 'Survey/Response', + }, + surveyEditTemplateId => { + tab => 'display', + fieldType => 'template', + label => "Survey edit template id", + defaultValue => 'GRUNFctldUgop-qRLuo_DA', + namespace => 'Survey/Edit', + }, + surveyTakeTemplateId => { + tab => 'display', + fieldType => 'template', + label => "Take survey template id", + defaultValue => 'd8jMMMRddSQ7twP4l1ZSIw', + namespace => 'Survey/Take', + }, + surveyQuestionsId => { + tab => 'display', + fieldType => 'template', + label => "Questions template id", + defaultValue => 'CxMpE_UPauZA3p8jdrOABw', + namespace => 'Survey/Take', + }, + sectionEditTemplateId => { + tab => 'display', + fieldType => 'template', + label => "Section Edit Tempalte", + defaultValue => '1oBRscNIcFOI-pETrCOspA', + namespace => 'Survey/Edit', + }, + questionEditTemplateId => { + tab => 'display', + fieldType => 'template', + label => "Question Edit Tempalte", + defaultValue => 'wAc4azJViVTpo-2NYOXWvg', + namespace => 'Survey/Edit', + }, + answerEditTemplateId => { + tab => 'display', + fieldType => 'template', + label => "Answer Edit Tempalte", + defaultValue => 'AjhlNO3wZvN5k4i4qioWcg', + namespace => 'Survey/Edit', + }, + ); + + push(@{$definition}, { + assetName=>$i18n->get('assetName'), + icon=>'survey.gif', + autoGenerateForms=>1, + tableName=>'Survey', + className=>'WebGUI::Asset::Wobject::Survey', + properties=>\%properties + }); return $class->SUPER::definition($session, $definition); } #------------------------------------------------------------------- + +=head2 exportAssetData ( ) + +Override exportAssetData so that surveyJSON is included in package exports etc.. + +=cut + +sub exportAssetData { + my $self = shift; + my $hash = $self->SUPER::exportAssetData(); + $self->loadSurveyJSON(); + $hash->{properties}{surveyJSON} = $self->survey->freeze; + return $hash; +} + +#------------------------------------------------------------------- + +=head2 importAssetData ( hashRef ) + +Override importAssetCollateralData so that surveyJSON gets imported from packages + +=cut + +sub importAssetCollateralData { + my ($self, $data) = @_; + my $surveyJSON = $data->{properties}{surveyJSON}; + $self->session->db->write("update Survey set surveyJSON = ? where assetId = ?",[$surveyJSON,$self->getId]); +} + +#------------------------------------------------------------------- + +=head2 duplicate ( ) + +Override duplicate so that surveyJSON gets duplicated too + +=cut + sub duplicate { my $self = shift; - my $newAsset = $self->SUPER::duplicate(@_); - my $newSurveyId = $self->session->id->generate(); - $newAsset->update({ - Survey_id=>$newSurveyId - }); - - my $sections = $self->session->db->read("select * from Survey_section where Survey_id=? order by sequenceNumber",[$self->get("Survey_id")]); - while (my $sdata = $sections->hashRef) { - my $oldSectionId = $sdata->{Survey_sectionId}; - $sdata->{Survey_sectionId} = "new"; - $sdata->{Survey_id} = $newSurveyId; - $sdata->{Survey_sectionId} = $newAsset->setCollateral("Survey_section", "Survey_sectionId",$sdata,1,0, "Survey_id"); - - my $questions = $self->session->db->read("select * from Survey_question where Survey_id=? and Survey_sectionId=?",[$self->get("Survey_id"), $oldSectionId]); - while (my $qdata = $questions->hashRef) { - my $oldQuestionId = $qdata->{Survey_questionId}; - $qdata->{Survey_questionId} = "new"; - $qdata->{Survey_id} = $newSurveyId; - $qdata->{Survey_sectionId} = $sdata->{Survey_sectionId}; - $qdata->{Survey_questionId} = $newAsset->setCollateral("Survey_question","Survey_questionId",$qdata,1,0,"Survey_id"); - my $answers = $self->session->db->read("select * from Survey_answer where Survey_questionId=? order by sequenceNumber",[$oldQuestionId]); - while (my $adata = $answers->hashRef) { - my $oldAnswerId = $adata->{Survey_answerId}; - $adata->{Survey_answerId} = "new"; - $adata->{Survey_questionId} = $qdata->{Survey_questionId}; - $adata->{Survey_id} = $newSurveyId; - $adata->{Survey_answerId} = $newAsset->setCollateral("Survey_answer", "Survey_answerId", $adata, 1, 0, "Survey_Id"); - my $responses = $self->session->db->read("select * from Survey_questionResponse where Survey_answerId=?",[$oldAnswerId]); - while (my $rdata = $responses->hashRef) { - $rdata->{Survey_responseId} = "new"; - $rdata->{Survey_answerId} = $adata->{Survey_answerId}; - $rdata->{Survey_id} = $newSurveyId; - $rdata->{Survey_questionId} = $qdata->{Survey_questionId}; - $newAsset->setCollateral("Survey_questionResponse","Survey_responseId",$rdata,0,0); - } - } - } - } - - return $newAsset; + my $options = shift; + my $newAsset = $self->SUPER::duplicate($options); + $self->loadSurveyJSON(); + $self->session->db->write("update Survey set surveyJSON = ? where assetId = ?",[$self->survey->freeze,$newAsset->getId]); + return $newAsset; } #------------------------------------------------------------------- -sub generateResponseId { - my $self = shift; - my $varname = $self->getResponseIdString; - if ($self->session->scratch->get($varname)) { - $self->completeResponse; - } - my $ipAddress = $self->getIp; - my $userId = $self->getUserId; - my $responseId = $self->session->db->setRow("Survey_response","Survey_responseId",{ - 'Survey_responseId'=>"new", - userId=>$userId, - ipAddress=>$ipAddress, - username=>$self->session->user->username, - startDate=>$self->session->datetime->time(), - 'Survey_id'=>$self->get("Survey_id") - }); - $self->session->scratch->set($varname,$responseId); - return $responseId; -} -#------------------------------------------------------------------- -sub getEditForm { - my $self = shift; - my $tabform = $self->SUPER::getEditForm; +=head2 getEditForm - my $i18n = WebGUI::International->new($self->session, 'Asset_Survey'); - $tabform->getTab('properties')->hidden( - -name => "Survey_id", - -value => ($self->get("Survey_id") || $self->session->id->generate()) - ); - $tabform->getTab('display')->template( - -name => 'templateId', - -label => $i18n->get('view template'), - -hoverHelp => $i18n->get('view template description'), - -value => $self->getValue('templateId'), - -namespace => 'Survey', - -afterEdit => 'func=edit' - ); - $tabform->getTab('display')->template( - -name => 'responseTemplateId', - -label => $i18n->get('response template'), - -hoverHelp => $i18n->get('response template description'), - -value => $self->getValue('responseTemplateId'), - -namespace => 'Survey/Response', - -afterEdit => 'func=edit' - ); - $tabform->getTab('display')->template( - -name => 'gradebookTemplateId', - -label => $i18n->get('gradebook template'), - -hoverHelp => $i18n->get('gradebook template description'), - -value => $self->getValue('gradebookTemplateId'), - -namespace => 'Survey/Gradebook', - -afterEdit => 'func=edit' - ); - $tabform->getTab('display')->template( - -name => 'overviewTemplateId', - -label => $i18n->get('overview template'), - -hoverHelp => $i18n->get('overview template description'), - -value => $self->getValue('overviewTemplateId'), - -namespace => 'Survey/Overview', - -afterEdit => 'func=edit' - ); +getEditForm is called when creating/editing the asset. +This overloads the normal call to the super, to call the super call like normal and then add to the tab form. - $tabform->getTab('display')->selectBox( - -name => "questionOrder", - -options => { - sequential => $i18n->get(5), - random => $i18n->get(6), - response => $i18n->get(7), - section => $i18n->get(106) - }, - -label => $i18n->get(8), - -hoverHelp => $i18n->get('8 description'), - -value => [$self->getValue("questionOrder")] - ); - $tabform->getTab('display')->integer( - -name => "questionsPerPage", - -value => $self->getValue("questionsPerPage"), - -label => $i18n->get(83), - -hoverHelp => $i18n->get('83 description') - ); - $tabform->getTab('properties')->selectBox( - -name => "mode", - -options => { - survey => $i18n->get(9), - quiz => $i18n->get(10) - }, - -label => $i18n->get(11), - -hoverHelp => $i18n->get('11 description'), - -value => [$self->getValue("mode")] - ); - $tabform->getTab('properties')->yesNo( - -name => "anonymous", - -value => $self->getValue("anonymous"), - -label => $i18n->get(81), - -hoverHelp => $i18n->get('81 description') - ); - $tabform->getTab('properties')->integer( - -name => "maxResponsesPerUser", - -value => $self->getValue("maxResponsesPerUser"), - -label => $i18n->get(84), - -hoverHelp => $i18n->get('84 description') - ); - $tabform->getTab('properties')->integer( - -name => "questionsPerResponse", - -value => $self->getValue("questionsPerResponse"), - -label => $i18n->get(85), - -hoverHelp => $i18n->get('85 description') - ); - $tabform->getTab('security')->group( - -name => "groupToTakeSurvey", - -value => [$self->getValue("groupToTakeSurvey")], - -label => $i18n->get(12), - -hoverHelp => $i18n->get('12 description') - ); - $tabform->getTab('security')->group( - -name => "groupToViewReports", - -label => $i18n->get(13), - -hoverHelp => $i18n->get('13 description'), - -value => [$self->getValue("groupToViewReports")] - ); - if ($self->get("assetId") eq "new") { - $tabform->getTab('properties')->whatNext( - -options=>{ - editQuestion=>$i18n->get(28), - viewParent=>$i18n->get(745) - }, - -value=>"editQuestion", - -hoverHelp => $i18n->get('what next description'), - ); - } +=cut - return $tabform; -} +#sub getEditForm { +# my $self = shift; -#------------------------------------------------------------------- -sub getIp { - my $self = shift; - my $ip = ($self->get("anonymous")) ? substr(md5_hex($self->session->env->getIp),0,8) : $self->session->env->getIp; - return $ip; -} +# my $tabform = $self->SUPER::getEditForm(@_); -#------------------------------------------------------------------- -sub getMenuVars { - my $self = shift; - my %var; - my $i18n = WebGUI::International->new($self->session,'Asset_Survey'); - $var{'user.canViewReports'} = ($self->session->user->isInGroup($self->get("groupToViewReports"))); - $var{'delete.all.responses.url'} = $self->getUrl('func=deleteAllResponses'); - $var{'delete.all.responses.label'} = $i18n->get(73); - $var{'export.answers.url'} = $self->getUrl('func=exportAnswers'); - $var{'export.answers.label'} = $i18n->get(62); - $var{'export.questions.url'} = $self->getUrl('func=exportQuestions'); - $var{'export.questions.label'} = $i18n->get(63); - $var{'export.responses.url'} = $self->getUrl('func=exportResponses'); - $var{'export.responses.label'} = $i18n->get(64); - $var{'export.composite.url'} = $self->getUrl('func=exportComposite'); - $var{'export.composite.label'} = $i18n->get(65); - $var{'report.gradebook.url'} = $self->getUrl('func=viewGradebook'); - $var{'report.gradebook.label'} = $i18n->get(61); - $var{'report.overview.url'} = $self->getUrl('func=viewStatisticalOverview'); - $var{'report.overview.label'} = $i18n->get(59); - $var{'survey.url'} = $self->getUrl; - $var{'survey.label'} = $i18n->get(60); - return \%var; -} +# $tabform->getTab("properties")->hidden( +# -value => "editSurvey", +# -name => 'proceed' +# ); -#------------------------------------------------------------------- -sub getQuestionCount { - my $self = shift; - my ($count) = $self->session->db->quickArray("select count(*) from Survey_question where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); - return ($count < $self->getValue("questionsPerResponse")) ? $count : $self->getValue("questionsPerResponse"); -} - -#------------------------------------------------------------------- -sub getQuestionsLoop { - my $self = shift; - my $responseId = shift; - my @ids; - if ($self->get("questionOrder") eq "sequential") { - @ids = $self->getSequentialQuestionIds($responseId); - } elsif ($self->get("questionOrder") eq "response") { - @ids = $self->getResponseDrivenQuestionIds($responseId); - } elsif ($self->get("questionOrder") eq "section") { - @ids = $self->getSectionDrivenQuestionIds($responseId); - } else { - @ids = $self->getRandomQuestionIds($responseId); - } - my $length = scalar(@ids); - my $i = 1; - my @loop; - - #Ignore questions per page when using sections, return all questions for current section - if ($self->get("questionOrder") eq "section") { - while ($i <= $length) { - push(@loop,$self->getQuestionVars($ids[($i-1)])); - $i++; - } - return \@loop; - } - - my $questionResponseCount = $self->getQuestionResponseCount($responseId); - while ($i <= $length && $i<= $self->get("questionsPerPage") && ($questionResponseCount + $i) <= $self->getValue("questionsPerResponse")) { - push(@loop,$self->getQuestionVars($ids[($i-1)])); - $i++; - } - return \@loop; -} - - -#------------------------------------------------------------------- -sub getQuestionResponseCount { - my $self = shift; - my $responseId = shift; - my ($count) = $self->session->db->quickArray("select count(*) from Survey_questionResponse where Survey_responseId=".$self->session->db->quote($responseId)); - return $count; -} - -#------------------------------------------------------------------- -sub getQuestionVars { - my $self = shift; - my $questionId = shift; - my $i18n = WebGUI::International->new($self->session,'Asset_Survey'); - my %var; - my $question = $self->session->db->getRow("Survey_question","Survey_questionId",$questionId); - $var{'question.question'} = $question->{question}; - $var{'question.allowComment'} = $question->{allowComment}; - $var{'question.id'} = $question->{Survey_questionId}; - $var{'question.comment.field'} = WebGUI::Form::textarea($self->session,{ - name=>'comment_'.$questionId - }); - $var{'question.comment.label'} = $i18n->get(51); - - my $answer; - ($answer) = $self->session->db->quickArray("select Survey_answerId from Survey_answer where Survey_questionId=".$self->session->db->quote($question->{Survey_questionId})); - $var{'question.answer.field'} = WebGUI::Form::hidden($self->session,{ - name=>'answerId_'.$questionId, - value=>$answer - }); - if ($question->{answerFieldType} eq "text") { - $var{'question.answer.field'} .= WebGUI::Form::text($self->session,{ - name=>'textResponse_'.$questionId - }); - } elsif ($question->{answerFieldType} eq "HTMLArea") { - $var{'question.answer.field'} .= WebGUI::Form::HTMLArea($self->session,{ - name=>'textResponse_'.$questionId - }); - } elsif ($question->{answerFieldType} eq "textArea") { - $var{'question.answer.field'} .= WebGUI::Form::textarea($self->session,{ - name=>'textResponse_'.$questionId - }); - } else { - my $answer = $self->session->db->buildHashRef("select Survey_answerId,answer from Survey_answer where Survey_questionId=? order by sequenceNumber", [$question->{Survey_questionId}]); - if ($question->{randomizeAnswers}) { - $answer = randomizeHash($answer); - } - $var{'question.answer.field'} = WebGUI::Form::radioList($self->session,{ - options=>$answer, - name=>"answerId_".$questionId, - vertical=>1 - }); - } - return \%var; -} - -#------------------------------------------------------------------- -sub getRandomQuestionIds { - my $self = shift; - my $responseId = shift; - my @usedQuestionIds = $self->session->db->buildArray("select Survey_questionId from Survey_questionResponse where Survey_responseId=".$self->session->db->quote($responseId)); - my $where = " where Survey_id=".$self->session->db->quote($self->get("Survey_id")); - if ($#usedQuestionIds+1 > 0) { - $where .= " and Survey_questionId not in (".$self->session->db->quoteAndJoin(\@usedQuestionIds).")"; - } - my @questions = $self->session->db->buildArray("select Survey_questionId from Survey_question".$where); - @questions = List::Util::shuffle(@questions); - return @questions; -} - -#------------------------------------------------------------------- -sub getResponseCount { - my $self = shift; - my $ipAddress = $self->getIp; - my $userId = $self->getUserId; - my ($count) = $self->session->db->quickArray("select count(*) from Survey_response where Survey_id=".$self->session->db->quote($self->get("Survey_id"))." and - ((userId<>'1' and userId=".$self->session->db->quote($userId).") or ( userId='1' and ipAddress=".$self->session->db->quote($ipAddress)."))"); - return $count; -} - - -#------------------------------------------------------------------- -sub getResponseDrivenQuestionIds { - my $self = shift; - my $responseId = shift; - my $previousResponse = $self->session->db->quickHashRef("select Survey_questionId, Survey_answerId from Survey_questionResponse - where Survey_responseId=".$self->session->db->quote($responseId)." order by dateOfResponse desc"); - my $questionId; - my @questions; - if ($previousResponse->{Survey_answerId}) { - ($questionId) = $self->session->db->quickArray("select gotoQuestion from Survey_answer where - Survey_answerId=".$self->session->db->quote($previousResponse->{Survey_answerId})); - unless ($questionId) { - ($questionId) = $self->session->db->quickArray("select gotoQuestion from Survey_question where - Survey_questionId=".$self->session->db->quote($previousResponse->{Survey_questionId})); - } - if (!$questionId || $questionId eq '-1') { # terminate survey - $self->completeResponse($responseId); - return (); - } - } else { - ($questionId) = $self->session->db->quickArray("select Survey_questionId from Survey_question where Survey_id=".$self->session->db->quote($self->getValue("Survey_id"))." - order by sequenceNumber"); - } - push(@questions,$questionId); - return @questions; -} - -#------------------------------------------------------------------- -sub getSectionDrivenQuestionIds { - my $self = shift; - my $responseId = shift; - my @usedQuestionIds = $self->session->db->buildArray("select Survey_questionId from Survey_questionResponse where Survey_responseId=".$self->session->db->quote($responseId)); - my @questions; - my $where = " where Survey_question.Survey_id=".$self->session->db->quote($self->get("Survey_id")); - $where .= " and Survey_question.Survey_sectionId=Survey_section.Survey_sectionId"; - - if ($#usedQuestionIds+1 > 0) { - $where .= " and Survey_questionId not in (".$self->session->db->quoteAndJoin(\@usedQuestionIds).")"; - } - - my $sth = $self->session->db->read("select Survey_questionId, Survey_question.Survey_sectionId from Survey_question, - Survey_section $where order by Survey_section.sequenceNumber, Survey_question.sequenceNumber"); - - my $loopCount=0; - my $currentSection; - while (my $hashRef = $sth->hashRef) { - if ($loopCount == 0){ $currentSection = $hashRef->{Survey_sectionId}; } - if ($currentSection eq $hashRef->{Survey_sectionId}) { - push (@questions, $hashRef->{Survey_questionId}); - } - $loopCount++; - } - $sth->finish; - return @questions; -} +# return $tabform; +# return $self->www_editSurvey(@_); +#} #------------------------------------------------------------------- -sub getResponseId { - my $self = shift; - return $self->session->scratch->get($self->getResponseIdString); +#sub processPropertiesFromFormPost { +# my $self = shift; +# $self->SUPER::processPropertiesFromFormPost; + +# $self->loadSurveyJSON(); +# if($#{$self->{_data}->{sections}} < 0){ +#$self->session->errorHandler->error("In Processing from Post\n"); +# my $section = $self->{_data}->newSection(); +# $self->{_data}->addSection($section); + +#$self->session->errorHandler->error("Processing from creation\n".Dumper $self->{_data}); +# } +# $self->saveSurveyJSON(); +#} + +#------------------------------------------------------------------- + +=head2 loadSurveyJSON ( ) + +Loads the survey collateral into memory so that the survey objects can be created + +=cut + +sub loadSurveyJSON{ + my $self = shift; + my $jsonHash = shift; + if(defined $self->survey){return;}#already loaded + + $jsonHash = $self->session->db->quickScalar("select surveyJSON from Survey where assetId = ?",[$self->getId]) if(! defined $jsonHash); + +eval{ + $self->{survey} = WebGUI::Asset::Wobject::Survey::SurveyJSON->new($jsonHash,$self->session->errorHandler); +}; } #------------------------------------------------------------------- -sub getResponseIdString { - my $self = shift; - return "Survey-".$self->get("Survey_id")."-ResponseId"; + +=head2 saveSurveyJSON ( ) + +Saves the survey collateral to the DB + +=cut + +sub survey{ return shift->{survey}; } +sub littleBuddy{ return shift->{survey}; } +sub allyourbases{ return shift->{survey}; } +sub helpmehelpme{ return shift->{survey}; } + +sub saveSurveyJSON{ + my $self = shift; + + my $data = $self->survey->freeze(); + + $self->session->db->write("update Survey set surveyJSON = ? where assetId = ?",[$data,$self->getId]); } #------------------------------------------------------------------- -sub getSequentialQuestionIds { - my $self = shift; - my $responseId = shift; - my @usedQuestionIds = $self->session->db->buildArray("select Survey_questionId from Survey_questionResponse where Survey_responseId=".$self->session->db->quote($responseId)); - my $where = " where Survey_id=".$self->session->db->quote($self->get("Survey_id")); - if ($#usedQuestionIds+1 > 0) { - $where .= " and Survey_questionId not in (".$self->session->db->quoteAndJoin(\@usedQuestionIds).")"; - } - my @questions = $self->session->db->buildArray("select Survey_questionId from Survey_question $where order by sequenceNumber"); - return @questions; + +=head2 www_editSurvey ( ) + +Loads the initial edit survey page. All other edit actions are JSON calls from this page. + +=cut + +sub www_editSurvey { + my $self = shift; + + my %var; + my $out = $self->processTemplate(\%var,$self->get("surveyEditTemplateId")); + + return $out; +} + + +#------------------------------------------------------------------- +sub www_submitObjectEdit{ + my $self = shift; + +# my $ref = @{decode_json($self->session->form->process("data"))}; + my $responses = $self->session->form->paramsHashRef(); + + my @address = split/-/,$responses->{id}; + + $self->loadSurveyJSON(); + if($responses->{delete}){ + return $self->deleteObject(\@address); + } + elsif($responses->{copy}){ + return $self->copyObject(\@address); + } + + #each object checks the ref and then either updates or passes it to the correct child. New objects will have an index of -1. + my $message = $self->survey->update(\@address,$responses); + + $self->saveSurveyJSON(); + + return $self->www_loadSurvey({address => \@address}); } #------------------------------------------------------------------- -sub getUserId { - my $self = shift; - my $userId = ($self->get("anonymous") && $self->session->user->userId != 1) ? substr(md5_hex($self->session->user->userId),0,8) : $self->session->user->userId; - return $userId; +sub copyObject{ + my ($self,$address) = @_; + + $self->loadSurveyJSON(); + + $address = $self->survey->copy($address);#each object checks the ref and then either updates or passes it to the correct child. New objects will have an index of -1. + + $self->saveSurveyJSON(); + #The parent address of the deleted object is returned. + + return $self->www_loadSurvey({address => $address}); +} + +#------------------------------------------------------------------- +sub deleteObject{ + my ($self,$address) = @_; + + $self->loadSurveyJSON(); + + my $message = $self->survey->remove($address);#each object checks the ref and then either updates or passes it to the correct child. New objects will have an index of -1. + + $self->saveSurveyJSON(); + #The parent address of the deleted object is returned. + if(@$address == 1){ + $$address[0] = 0; + }else{ + pop(@{$address});# unless @$address == 1 and $$address[0] == 0; + } + + return $self->www_loadSurvey({address => $address, message=>$message}); +} + + +#------------------------------------------------------------------- +sub www_newObject{ + my $self = shift; + my $ref; + + my $ids = $self->session->form->process("data"); + + my @inAddress = split/-/,$ids; + + $self->loadSurveyJSON(); + + #Don't save after this as the new object should not stay in the survey + my $address = $self->survey->newObject(\@inAddress); + + + #The new temp object has an address of NEW, which means it is not a real final address. + + return $self->www_loadSurvey({address => $address, message => undef}); + +} + + +#------------------------------------------------------------------- +sub www_dragDrop{ + my $self = shift; + my $p = decode_json($self->session->form->process("data")); + + + my @tid = split/-/,$p->{target}->{id}; + my @bid = split/-/,$p->{before}->{id}; + + $self->loadSurveyJSON(); + my $target = $self->survey->getObject(\@tid); + $self->survey->remove(\@tid,1); + my $address = [0]; + if(@tid == 1){ + $#bid = 0;#sections can only be inserted after another section so chop off the question and answer portion of + $bid[0] = -1 if(! defined $bid[0]); + $self->survey->insertObject($target, [$bid[0]]); + }elsif(@tid == 2){#questions can be moved to any section, but a pushed to the end of a new section. + if($bid[0] !~ /\d/){ + $bid[0] = $tid[0]; + $bid[1] = $tid[1]; + }elsif(@bid == 1){#moved to a new section or head of current section + if($bid[0] !~ /\d/){ + $bid[0] = $tid[0]; + $bid[1] = $tid[1]; + } + if($bid[0] == $tid[0]){ + #moved to top of current section + $bid[1] = -1; + }else{ + #else move to the end of the selected section + $bid[1] = $#{$self->survey->questions([$bid[0]])}; + } + } + $self->survey->insertObject($target, [$bid[0],$bid[1]]); + }elsif(@tid == 3){#answers can only be rearranged in the same question + if(@bid == 2 and $bid[1] == $tid[1]){ + $bid[2] = -1; + $self->survey->insertObject($target, [$bid[0],$bid[1],$bid[2]]); + }elsif(@bid == 3){ + $self->survey->insertObject($target, [$bid[0],$bid[1],$bid[2]]); + }else{ + #else put it back where it was + $self->survey->insertObject($target, \@tid); + } + } + + $self->saveSurveyJSON(); + + return $self->www_loadSurvey({address => $address}); +} + + +#------------------------------------------------------------------- +sub www_loadSurvey{ + my ($self,$options) = @_; + + $self->loadSurveyJSON(); + + my $address = defined $options->{address} ? $options->{address} : undef; + if(! defined $address){ + if(my $inAddress = $self->session->form->process("data")){ + $address = [split/-/,$inAddress]; + }else{ + $address = [0]; + } + } + my $message = defined $options->{message} ? $options->{message} : ''; + my $var = defined $options->{var} ? $options->{var} : $self->survey->getEditVars($address); + + my $editHtml; + if($var->{type} eq 'section'){ + $editHtml = $self->processTemplate($var,$self->get("sectionEditTemplateId")); + }elsif($var->{type} eq 'question'){ + $editHtml = $self->processTemplate($var,$self->get("questionEditTemplateId")); + }elsif($var->{type} eq 'answer'){ + $editHtml = $self->processTemplate($var,$self->get("answerEditTemplateId")); + } + + my %buttons; + $buttons{question} = $$address[0]; + if(@$address == 2 or @$address == 3){ + $buttons{answer} = "$$address[0]-$$address[1]"; + } + + my $data = $self->survey->getDragDropList($address); + my $html; + my ($scount,$qcount,$acount) = (-1,-1,-1); + my $lastType; + my %lastId; + my @ids; + my ($s,$q,$a) = (0,0,0);#bools on if a button has already been created + + foreach (@$data){ + if($_->{type} eq 'section'){ + $lastId{section} = ++$scount; + if($lastType eq 'answer'){ + $a = 1; + } + elsif($lastType eq 'question'){ + $q = 1; + } + $html .= "
  • S". ($scount + 1). ": $_->{text}<\/li>
    \n"; + push(@ids,$scount); + } + elsif($_->{type} eq 'question'){ + $lastId{question} = ++$qcount; + if($lastType eq 'answer'){ + $a = 1; + } + $html .= "
  • Q". ($qcount + 1). ": $_->{text}<\/li>
    \n"; + push(@ids,"$scount-$qcount"); + $lastType = 'question'; + $acount = -1; + } + elsif($_->{type} eq 'answer'){ + $lastId{answer} = ++$acount; + $html .= "
  • A". ($acount + 1). ": $_->{text}<\/li>
    \n"; + push(@ids,"$scount-$qcount-$acount"); + $lastType = 'answer'; + } + } + + #address is the address of the focused object + #buttons are the data to create the Add buttons + #edithtml is the html edit the object + #ddhtml is the html to create the draggable html divs + #ids is a list of all ids passed in which are draggable (for adding events) + #type is the object type + my $return = {"address",$address,"buttons",\%buttons,"edithtml",$editHtml,"ddhtml",$html,"ids",\@ids,"type",$var->{type}}; + $self->session->http->setMimeType('application/json'); + return encode_json($return); } #------------------------------------------------------------------- @@ -570,564 +513,453 @@ See WebGUI::Asset::prepareView() for details. =cut sub prepareView { - my $self = shift; - $self->SUPER::prepareView(); - my $template = WebGUI::Asset::Template->new($self->session, $self->get("templateId")); - $template->prepare($self->getMetaDataAsTemplateVariables); - $self->{_viewTemplate} = $template; + my $self = shift; + $self->SUPER::prepareView(); + my $templateId = $self->get("templateId"); + if ($self->session->form->process("overrideTemplateId") ne "") { + $templateId = $self->session->form->process("overrideTemplateId"); + } + my $template = WebGUI::Asset::Template->new($self->session, $templateId); + $template->prepare; + $self->{_viewTemplate} = $template; } +#------------------------------------------------------------------- -#------------------------------------------------------------------- -sub processPropertiesFromFormPost { - my $self = shift; - $self->SUPER::processPropertiesFromFormPost; - my $i18n = WebGUI::International->new($self->session,"Asset_Survey"); - if ($self->session->form->process("assetId") eq "new") { - my $defaultSectionId = $self->addSection($i18n->get(107)); - $self->update({'defaultSectionId' => $defaultSectionId}); - $self->session->errorHandler->warn($defaultSectionId); - } - -} -#------------------------------------------------------------------- sub purge { - my $self = shift; - my ($count) = $self->session->db->quickArray("select count(*) from Survey where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); - if ($count < 2) { ### Check for other wobjects using this survey. - $self->session->db->write("delete from Survey_question where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); - $self->session->db->write("delete from Survey_answer where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); - $self->session->db->write("delete from Survey_response where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); - $self->session->db->write("delete from Survey_section where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); - } - $self->SUPER::purge(); -} - - -#------------------------------------------------------------------- -sub responseIsComplete { - my $self = shift; - my $responseId = shift; - my $response = $self->session->db->getRow("Survey_response","Survey_responseId",$responseId); - return $response->{isComplete}; -} - - -#------------------------------------------------------------------- -sub setAnswerType { - my $self = shift; - my $answerFieldType = shift; - my $qid = shift; - $self->setCollateral("Survey_question","Survey_questionId",{ - Survey_questionId=>$qid, - Survey_id=>$self->get("Survey_id"), - answerFieldType=>$answerFieldType - },1,0,"Survey_id"); -} - -#------------------------------------------------------------------- -sub view { - my $self = shift; - my $i18n = WebGUI::International->new($self->session, 'Asset_Survey'); - my $var = $self->getMenuVars; - $var->{'question.add.url'} = $self->getUrl('func=editQuestion;qid=new'); - $var->{'question.add.label'} = $i18n->get(30); - $var->{'section.add.url'} = $self->getUrl('func=editSection;sid=new'); - $var->{'section.add.label'} = $i18n->get(104); - my @sectionEdit; - - # Get Sections - my $sth = $self->session->db->read("select Survey_sectionId,sectionName from Survey_section where Survey_id=".$self->session->db->quote($self->get("Survey_id"))." order by sequenceNumber"); - while (my %sectionData = $sth->hash) { - my @edit; - - # Get Questions for this section - my $sth2 = $self->session->db->read("select Survey_questionId,question from Survey_question - where Survey_id=".$self->session->db->quote($self->get("Survey_id"))." - and Survey_sectionId=".$self->session->db->quote($sectionData{Survey_sectionId})." order by sequenceNumber"); - while (my %data = $sth2->hash) { - push(@edit,{ - 'question.edit.controls'=> - $self->session->icon->delete('func=deleteQuestionConfirm;qid='.$data{Survey_questionId}, $self->get("url"), $i18n->get(44)). - $self->session->icon->edit('func=editQuestion;qid='.$data{Survey_questionId}, $self->get("url")). - $self->session->icon->moveUp('func=moveQuestionUp;qid='.$data{Survey_questionId}, $self->get("url")). - $self->session->icon->moveDown('func=moveQuestionDown;qid='.$data{Survey_questionId}, $self->get("url")), - 'question.edit.question'=>$data{question}, - 'question.edit.id'=>$data{Survey_questionId} - }); - } - $sth2->finish; - - push(@sectionEdit,{ - 'section.edit.controls'=> - $self->session->icon->delete('func=deleteSectionConfirm;sid='.$sectionData{Survey_sectionId}, $self->get("url"), $i18n->get(105)). - $self->session->icon->edit('func=editSection;sid='.$sectionData{Survey_sectionId}, $self->get("url")). - $self->session->icon->moveUp('func=moveSectionUp;sid='.$sectionData{Survey_sectionId}, $self->get("url")). - $self->session->icon->moveDown('func=moveSectionDown;sid='.$sectionData{Survey_sectionId}, $self->get("url")), - 'section.edit.sectionName'=>$sectionData{sectionName}, - 'section.edit.id'=>$sectionData{Survey_sectionId}, - 'section.questions_loop'=>\@edit - }); - $var->{'section.edit_loop'} = \@sectionEdit; - - } - $sth->finish; - - $var->{'user.canTakeSurvey'} = $self->session->user->isInGroup($self->get("groupToTakeSurvey")); - if ($var->{'user.canTakeSurvey'}) { - $var->{'response.Id'} = $self->getResponseId; - $var->{'response.Count'} = $self->getResponseCount; - $var->{'user.isFirstResponse'} = ($var->{'response.Count'} == 0 && !(exists $var->{'response.id'})); - $var->{'user.canRespondAgain'} = ($var->{'response.Count'} < $self->get("maxResponsesPerUser")); - if ($self->session->form->process("startNew") && $var->{'user.canRespondAgain'}) { - $var->{'response.Id'} = "new"; - } - elsif ($var->{'user.isFirstResponse'}) { - $var->{'response.Id'} ||= "new"; - } - if ($var->{'response.Id'}) { - $var->{'questions.soFar.count'} = $self->getQuestionResponseCount($var->{'response.Id'}); - ($var->{'questions.correct.count'}) = $self->session->db->quickArray("select count(*) from Survey_questionResponse a, Survey_answer b where a.Survey_responseId=" - .$self->session->db->quote($var->{'response.Id'})." and a.Survey_answerId=b.Survey_answerId and b.isCorrect=1"); - if ($var->{'questions.soFar.count'} > 0) { - $var->{'questions.correct.percent'} = round(($var->{'questions.correct.count'}/$var->{'questions.soFar.count'})*100) - } - $var->{question_loop} = $self->getQuestionsLoop($var->{'response.Id'}); - $var->{'response.isComplete'} = $self->responseIsComplete($var->{'response.Id'}); - } - } - $var->{'form.header'} = WebGUI::Form::formHeader($self->session,{action=>$self->getUrl}) - .WebGUI::Form::hidden($self->session,{ - name=>'func', - value=>'respond' - }); - if ($var->{'response.Id'}) { - $var->{'form.header'} .= WebGUI::Form::hidden($self->session,{name=>'responseId',value=>$var->{'response.Id'}}); - } - $var->{'form.footer'} = WebGUI::Form::formFooter($self->session,); - $var->{'form.submit'} = WebGUI::Form::submit($self->session,{ - value=>$i18n->get(50) - }); - $var->{'questions.sofar.label'} = $i18n->get(86); - $var->{'start.newResponse.label'} = $i18n->get(87); - $var->{'start.newResponse.url'} = $self->getUrl("func=view;startNew=1"); - $var->{'thanks.survey.label'} = $i18n->get(46); - $var->{'thanks.quiz.label'} = $i18n->get(47); - $var->{'questions.total'} = $self->getQuestionCount; - $var->{'questions.correct.count.label'} = $i18n->get(52); - $var->{'questions.correct.percent.label'} = $i18n->get(54); - $var->{'mode.isSurvey'} = ($self->get("mode") eq "survey"); - $var->{'survey.noprivs.label'} = $i18n->get(48); - $var->{'quiz.noprivs.label'} = $i18n->get(49); - return $self->processTemplate($var, undef, $self->{_viewTemplate}); -} - -#------------------------------------------------------------------- -sub www_deleteAnswerConfirm { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - my ($answerCount) = $self->session->db->quickArray("select count(*) from Survey_answer where Survey_questionId=".$self->session->db->quote($self->session->form->process("qid"))); - return $self->i18n("cannot delete the last answer") unless($answerCount); - $self->session->db->write("delete from Survey_questionResponse where Survey_answerId=".$self->session->db->quote($self->session->form->process("aid"))); - $self->deleteCollateral("Survey_answer","Survey_answerId",$self->session->form->process("aid")); - $self->reorderCollateral("Survey_answer","Survey_answerId","Survey_id"); - return $self->www_editQuestion; -} - -#------------------------------------------------------------------- -sub www_deleteQuestionConfirm { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - $self->session->db->write("delete from Survey_answer where Survey_questionId=".$self->session->db->quote($self->session->form->process("qid"))); - $self->session->db->write("delete from Survey_questionResponse where Survey_questionId=".$self->session->db->quote($self->session->form->process("qid"))); - $self->deleteCollateral("Survey_question","Survey_questionId",$self->session->form->process("qid")); - $self->reorderCollateral("Survey_question","Survey_questionId","Survey_id"); - return ""; -} - -#------------------------------------------------------------------- -sub www_deleteSectionConfirm { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - my $i18n = WebGUI::International->new($self->session,'Asset_Survey'); - my $section_id = $self->session->form->get("sid"); - if ($section_id eq $self->get("defaultSectionId")) { - return $self->session->privilege->vitalComponent(); - } - - $self->session->db->write("delete from Survey_section where Survey_sectionId=?",[$section_id]); - $self->deleteCollateral("Survey_section","Survey_sectionId",$section_id); - $self->reorderCollateral("Survey_section","Survey_sectionId","Survey_id"); - return ""; -} - -#------------------------------------------------------------------- -sub www_deleteResponse { - my $self = shift; - return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); - my $i18n = WebGUI::International->new($self->session, 'Asset_Survey'); - return $self->session->style->process($self->confirm($i18n->get(72), - $self->getUrl('func=deleteResponseConfirm;responseId='.$self->session->form->process("responseId"))),$self->getValue("styleTemplateId")); -} - -#------------------------------------------------------------------- -sub www_deleteResponseConfirm { - my $self = shift; - return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); - $self->session->db->write("delete from Survey_response where Survey_responseId=".$self->session->db->quote($self->session->form->process("responseId"))); - $self->session->db->write("delete from Survey_questionResponse where Survey_responseId=".$self->session->db->quote($self->session->form->process("responseId"))); - return $self->www_viewGradebook; -} - -#------------------------------------------------------------------- -sub www_deleteAllResponses { - my $self = shift; - return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); - my $i18n = WebGUI::International->new($self->session,'Asset_Survey'); - return $self->session->style->process($self->confirm($i18n->get(74),$self->getUrl('func=deleteAllResponsesConfirm')),$self->getValue("styleTemplateId")); -} - -#------------------------------------------------------------------- -sub www_deleteAllResponsesConfirm { - my $self = shift; - return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); - $self->session->db->write("delete from Survey_response where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); - $self->session->db->write("delete from Survey_questionResponse where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); - return ""; -} - -#------------------------------------------------------------------- -sub www_editAnswer { - my $self = shift; - my ($question, $f, $answer); - return $self->session->privilege->insufficient() unless ($self->canEdit); - my $aid = shift || $self->session->form->process('aid'); - my $qid = shift || $self->session->form->process('qid'); - - my $i18n = WebGUI::International->new($self->session,'Asset_Survey'); - $answer = $self->getCollateral("Survey_answer","Survey_answerId",$aid); - $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl); - $f->hidden( - -name => "assetId", - -value => $self->session->form->process("assetId") - ); - $f->hidden( - -name => "func", - -value => "editAnswerSave" - ); - $f->hidden( - -name => "qid", - -value => $qid - ); - $f->hidden( - -name => "aid", - -value => $answer->{Survey_answerId} - ); - $f->text( - -name=>"answer", - -value=>$answer->{answer}, - -label=>$i18n->get(19), - -hoverHelp=>$i18n->get('19 description') - ); - if ($self->get("mode") eq "quiz") { - $f->yesNo( - -name=>"isCorrect", - -value=>$answer->{isCorrect}, - -label=>$i18n->get(20), - -hoverHelp=>$i18n->get('20 description') - ); - } else { - $f->hidden( - -name => "isCorrect", - -value => 0 - ); - } - if ($self->get("questionOrder") eq "response") { - $question = $self->session->db->buildHashRef("select Survey_questionId,question - from Survey_question where Survey_id=".$self->session->db->quote($self->get("Survey_id"))." order by sequenceNumber"); - $question = { ('-1' => $i18n->get(82),%$question) }; - $f->selectBox( - -name=>"gotoQuestion", - -options=>$question, - -value=>[$answer->{gotoQuestion}], - -label=>$i18n->get(21), - -hoverHelp=>$i18n->get('21 description') - ); - } - if ($answer->{Survey_answerId} eq "new") { - my %options; - tie %options, 'Tie::IxHash'; - %options = ( - "addAnswer"=>$i18n->get(24), - "addQuestion"=>$i18n->get(28), - "editQuestion"=>$i18n->get(75), - "backToPage"=>$i18n->get(745) - ); - $f->whatNext( - -options=>\%options, - -value=>"addAnswer", - -hoverHelp=>$i18n->get('what next answer description') - ); - } - $f->submit; - - return $self->getAdminConsole->render($f->print, $i18n->get(18)); - -} - -#------------------------------------------------------------------- -sub www_editAnswerSave { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - my $qid = $self->session->form->process("qid"); - $self->setCollateral("Survey_answer", "Survey_answerId", { - Survey_answerId => $self->session->form->process("aid"), - Survey_questionId => $qid, - answer => $self->session->form->process("answer"), - isCorrect => $self->session->form->process("isCorrect"), - Survey_id=>$self->get("Survey_id"), - gotoQuestion => $self->session->form->process("gotoQuestion") - },1,0,"Survey_questionId", $qid); - if ($self->session->form->process("proceed") eq "addQuestion") { - return $self->www_editQuestion('new'); - } elsif ($self->session->form->process("proceed") eq "addAnswer") { - return $self->www_editAnswer('new'); - } elsif ($self->session->form->process("proceed") eq "backToPage") { - return ""; - } - return $self->www_editQuestion(); -} - -#------------------------------------------------------------------- -sub www_editQuestion { - my $self = shift; - my ($f, $question, $answerFieldType, $sth, %data); - my $qid = shift || $self->session->form->process('qid'); - - return $self->session->privilege->insufficient() unless ($self->canEdit); - - my $i18n = WebGUI::International->new($self->session,'Asset_Survey'); - tie %data, 'Tie::CPHash'; - $question = $self->getCollateral("Survey_question","Survey_questionId", $qid); - $answerFieldType = $question->{answerFieldType} || "radioList"; - - $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl); - $f->hidden( - -name => "assetId", - -value => $self->get("assetId") - ); - $f->hidden( - -name => "func", - -value => "editQuestionSave" - ); - $f->hidden( - -name => "qid", - -value => $question->{Survey_questionId} - ); - $f->hidden( - -name => "answerFieldType", - -value => $answerFieldType - ); - $f->HTMLArea( - -name => "question", - -value => $question->{question}, - -label => $i18n->get(14), - -hoverHelp => $i18n->get('14 description') - ); - $f->yesNo( - -name => "allowComment", - -value => $question->{allowComment}, - -label => $i18n->get(15), - -hoverHelp => $i18n->get('15 description') - ); - $f->yesNo( - -name => "randomizeAnswers", - -value => $question->{randomizeAnswers}, - -label => $i18n->get(16), - -hoverHelp => $i18n->get('16 description') - ); - - my $sectionList = $self->session->db->buildHashRef("select Survey_sectionId,sectionName - from Survey_section where Survey_id=".$self->session->db->quote($self->get("Survey_id"))." order by sequenceNumber"); - - $f->selectBox( - -name => "section", - -options=> $sectionList, - -value => [$question->{Survey_sectionId}], - -label => $i18n->get(106), - -hoverHelp => $i18n->get('106 description'), - ); - - if ($self->get("questionOrder") eq "response") { - my $ql = $self->session->db->buildHashRef("select Survey_questionId,question - from Survey_question where Survey_id=".$self->session->db->quote($self->get("Survey_id"))." order by sequenceNumber"); - $ql = { ('-1' => $i18n->get(82),%$ql) }; - $f->selectBox( - -name => "gotoQuestion", - -options=> $ql, - -value => [$question->{gotoQuestion}], - -label => $i18n->get(21), - -hoverHelp => $i18n->get('21 description') - ); - } - - if ($question->{Survey_questionId} eq "new") { - my %options; - tie %options, 'Tie::IxHash'; - %options = ( - "addMultipleChoiceAnswer" => $i18n->get(24), - "addTextAnswer" => $i18n->get(29), - "addBooleanAnswer" => $i18n->get(25), - "addFrequencyAnswer" => $i18n->get(26), - "addOpinionAnswer" => $i18n->get(27), - "addHTMLAreaAnswer" => $i18n->get(100), - "addTextAreaAnswer" => $i18n->get(101), - #"addQuestion" => $i18n->get(28), - "backToPage" => $i18n->get(745) - ); - $f->whatNext( - -options=> \%options, - -value => "addMultipleChoiceAnswer", - -hoverHelp => $i18n->get('what next question description') - ); - } - $f->submit; - my $output = $f->print; - if ($question->{Survey_questionId} ne "new" - && $question->{answerFieldType} ne "text" - && $question->{answerFieldType} ne "HTMLArea" - && $question->{answerFieldType} ne "textArea" - ) { - $output .= ''.$i18n->get(23).'

    '; - $sth = $self->session->db->read("select Survey_answerId,answer from Survey_answer - where Survey_questionId=".$self->session->db->quote($question->{Survey_questionId})." order by sequenceNumber"); - while (%data = $sth->hash) { - $output .= - $self->session->icon->delete('func=deleteAnswerConfirm;qid='.$question->{Survey_questionId}.';aid='.$data{Survey_answerId}, - $self->get("url"),$i18n->get(45)). - $self->session->icon->edit('func=editAnswer;qid='.$question->{Survey_questionId}.';aid='.$data{Survey_answerId}, $self->get("url")). - $self->session->icon->moveUp('func=moveAnswerUp'.';qid='.$question->{Survey_questionId}.';aid='.$data{Survey_answerId}, $self->get("url")). - $self->session->icon->moveDown('func=moveAnswerDown;qid='.$question->{Survey_questionId}.';aid='.$data{Survey_answerId}, $self->get("url")). - ' '.$data{answer}.'
    '; - } - $sth->finish; - } - return $self->getAdminConsole->render($output, $i18n->get(17)); -} - -#------------------------------------------------------------------- -sub www_editQuestionSave { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - - my $qid = $self->setCollateral("Survey_question", "Survey_questionId", { - # XXX: In some cases not all form fields are present and then the SQL query failes - # because the array is not complete - # There has to be a better way to fix this problem, but adding "|| 1" works for now - question=>$self->session->form->process("question", 'HTMLArea') || 1, - Survey_questionId=>$self->session->form->process("qid") || 1, - Survey_id=>$self->get("Survey_id") || 1, - allowComment=>$self->session->form->process("allowComment", 'yesNo'), - gotoQuestion=>$self->session->form->process("gotoQuestion", 'selectBox') || 1, - answerFieldType=>$self->session->form->process("answerFieldType") || 1, - randomizeAnswers=>$self->session->form->process("randomizeAnswers", 'yesNo'), - Survey_sectionId=>$self->session->form->process("section") || 1 - },1,0,"Survey_id"); - - if ($self->session->form->process("proceed") eq "addMultipleChoiceAnswer") { - return $self->www_editAnswer('new',$qid); - } elsif ($self->session->form->process("proceed") eq "addTextAnswer") { - $self->setAnswerType("text",$qid); - $self->addAnswer(0,$qid); - } elsif ($self->session->form->process("proceed") eq "addBooleanAnswer") { - $self->addAnswer(31,$qid); - $self->addAnswer(32,$qid); - } elsif ($self->session->form->process("proceed") eq "addOpinionAnswer") { - $self->addAnswer(33,$qid); - $self->addAnswer(34,$qid); - $self->addAnswer(35,$qid); - $self->addAnswer(36,$qid); - $self->addAnswer(37,$qid); - $self->addAnswer(38,$qid); - $self->addAnswer(39,$qid); - } elsif ($self->session->form->process("proceed") eq "addFrequencyAnswer") { - $self->addAnswer(40,$qid); - $self->addAnswer(41,$qid); - $self->addAnswer(42,$qid); - $self->addAnswer(43,$qid); - $self->addAnswer(39,$qid); - } elsif ($self->session->form->process("proceed") eq "addHTMLAreaAnswer") { - $self->setAnswerType("HTMLArea",$qid); - $self->addAnswer(0,$qid); - } elsif ($self->session->form->process("proceed") eq "addTextAreaAnswer") { - $self->setAnswerType("textArea",$qid); - $self->addAnswer(0,$qid); - } elsif ($self->session->form->process("proceed") eq "addQuestion") { - return $self->www_editQuestion('new'); - } - return ""; -} - -#------------------------------------------------------------------- -sub www_editSection { - my $self = shift; - my ($f, $section, $sectionName); - my $i18n = WebGUI::International->new($self->session, 'Asset_Survey'); - return $self->session->privilege->insufficient() unless ($self->canEdit); - $section = $self->getCollateral("Survey_section","Survey_sectionId",$self->session->form->process("sid")); - - if ($section->{Survey_sectionId} eq $self->get("defaultSectionId") && $section->{Survey_sectionId} ne "") { - return $self->session->privilege->vitalComponent; - } - - $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl); - $f->hidden( - -name => "assetId", - -value => $self->get("assetId") - ); - $f->hidden( - -name => "func", - -value => "editSectionSave" - ); - $f->hidden( - -name => "sid", - -value => $section->{Survey_sectionId} - ); - - $f->text( - -name => "sectionName", - -value => $section->{sectionName}, - -label => $i18n->get(102) - ); - $f->submit; - my $output = $f->print; - return $self->getAdminConsole->render($output, $i18n->get(103)); -} - -#------------------------------------------------------------------- -sub www_editSectionSave { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - $self->setCollateral("Survey_section", "Survey_sectionId", { - sectionName => $self->session->form->process("sectionName"), - Survey_sectionId=>$self->session->form->process("sid"), - Survey_id=>$self->get("Survey_id"), - },1,0,"Survey_id"); - return ""; -} - -#------------------------------------------------------------------- -sub www_exportAnswers { my $self = shift; + $self->session->db->write("delete from Survey_response where assetId = ?",[$self->getId()]); + $self->session->db->write("delete from Survey_tempReport where assetId = ?",[$self->getId()]); + $self->session->db->write("delete from Survey where assetId = ?",[$self->getId()]); + return $self->SUPER::purge; +} + +#------------------------------------------------------------------- + +=head2 purgeCache ( ) + +See WebGUI::Asset::purgeCache() for details. + +=cut + +sub purgeCache { + my $self = shift; + WebGUI::Cache->new($self->session,"view_".$self->getId)->delete; + $self->SUPER::purgeCache; +} + +#------------------------------------------------------------------- + +sub purgeRevision { + my $self = shift; + return $self->SUPER::purgeRevision; +} + +#------------------------------------------------------------------- + +=head2 view ( ) + +view defines all template variables, processes the template and +returns the output. + +=cut + +sub view { + my $self = shift; + my %var; + + $var{'edit_survey_url'} = $self->getUrl('func=editSurvey'); + $var{'take_survey_url'} = $self->getUrl('func=takeSurvey'); + $var{'view_reports_url'} = $self->getUrl('func=viewReports'); + $var{'user_canTakeSurvey'} = $self->session->user->isInGroup($self->get("groupToTakeSurvey")); + $var{'user_canViewReports'} = $self->session->user->isInGroup($self->get("groupToViewReports")); + $var{'user_canEditSurvey'} = $self->session->user->isInGroup($self->get("groupToEditSurvey")); + my $out = $self->processTemplate(\%var,undef,$self->{_viewTemplate}); + + return $out; +} + + +#------------------------------------------------------------------- + +=head2 www_view ( ) + +See WebGUI::Asset::Wobject::www_view() for details. + +=cut + +sub www_view { + my $self = shift; + $self->SUPER::www_view(@_); +} + + +#------------------------------------------------------------------- +sub www_takeSurvey{ + my $self = shift; + my %var; + + my $out = $self->processTemplate(\%var,$self->get("surveyTakeTemplateId")); + + eval{ + my $responseId = $self->getResponseId(); + if(!$responseId){ + return $self->surveyEnd(); + } + }; + + return $out; +} + + + + + +#handles questions that were submitted +#------------------------------------------------------------------- +sub www_submitQuestions{ + my $self=shift; + #can user take survey + if(!$self->canTakeSurvey()){ + # return encode_json({"type","FAIL LOGIN"}); + return $self->surveyEnd(); + } + + my $responseId = $self->getResponseId(); + if(!$responseId){return $self->surveyEnd();} + + + my $responses = $self->session->form->paramsHashRef(); + delete $$responses{'func'}; + + my @goodResponses = keys %$responses;#load everything. + + $self->loadBothJSON(); + + my $termInfo = $self->response->recordResponses($responses); + + $self->saveResponseJSON(); + + if($termInfo->[0]){ + return $self->surveyEnd($termInfo->[1]); + } + + return $self->www_loadQuestions(); + + my $files = 0; + +# for my $id(@$orderOf){ + #if a file upload, write to disk +# my $path; +# if($id->{'questionType'} eq 'File Upload'){ +# $files = 1; +# my $storage = WebGUI::Storage->create($self->session); +# my $filename = $storage->addFileFromFormPost( $id->{'Survey_answerId'} ); +# $path = $storage->getPath($filename); +# } +#$self->session->errorHandler->error("Inserting a response ".$id->{'Survey_answerId'}." $responseId, $path, ".$$responses{$id->{'Survey_answerId'}}); +# $self->session->db->write("insert into Survey_questionResponse +# select ?, Survey_sectionId, Survey_questionId, Survey_answerId, ?, ?, ?, now(), ?, ? from Survey_answer where Survey_answerId = ?", +# [$self->getId(), $responseId, $$responses{ $id->{'Survey_answerId'} }, '', $path, ++$lastOrder, $id->{'Survey_answerId'}]); +# } + if($files){ + ##special case, need to check for more questions in section, if not, more current up one + my $lastA = $self->getLastAnswerInfo($responseId); + my $questionId = $self->getNextQuestionId($lastA->{'Survey_questionId'}); + if(!$questionId){ + my $currentSection = $self->getCurrentSection($responseId); + $currentSection = $self->getNextSection($currentSection); + if($currentSection){ + $self->setCurrentSection($responseId,$currentSection); + } + } + return; + } + return $self->www_loadQuestions($responseId); +} + + + + + + +#finds the questions to display next and builds the data structre to hold them +#------------------------------------------------------------------- +sub www_loadQuestions{ + my $self=shift; + + + if(!$self->canTakeSurvey()){ + return $self->surveyEnd(); + } + + my $responseId = $self->getResponseId();#also loads the survey and response + if(!$responseId){ + return $self->surveyEnd(); + } + + return $self->surveyEnd() if($self->response->surveyEnd()); + + my $questions; +eval{ + $questions = $self->response->nextQuestions(); +}; + + + + my $section = $self->response->nextSection(); + + #return $self->prepareShowSurveyTemplate($section,$questions); + $section->{id} = $self->response->nextSectionId(); + my $text = $self->prepareShowSurveyTemplate($section,$questions); + return $text; +} + +#------------------------------------------------------------------- +#called when the survey is over. +sub surveyEnd{ + my $self = shift; + my $url = shift; + my $responseId = $self->getResponseId();#also loads the survey and response +# $self->session->db->write("update Survey_response set endDate = ? and isComplete = 1 where Survey_responseId = ?",[WebGUI::DateTime->now->toDatabase,$responseId]); + $self->session->db->setRow("Survey_response","Survey_responseId",{ + Survey_responseId=>$responseId, + endDate=>WebGUI::DateTime->now->toDatabase, + isComplete=>1 + }); + if($url !~ /\w/){ $url = 0; } + if($url eq "undefined"){ $url = 0; } + if(!$url){ + $url = $self->session->db->quickScalar("select exitURL from Survey where assetId = ? order by revisionDate desc limit 1",[$self->getId()]); + if(!$url){ + $url = "/"; + } + } + $self->session->http->setMimeType('application/json'); + return encode_json({"type","forward","url",$url}); +} + + + +#------------------------------------------------------------------- +#sends the processed template and questions structure to the client +sub prepareShowSurveyTemplate{ + my ($self,$section,$questions) = @_; + my %multipleChoice = ('Multiple Choice',1,'Gender',1,'Yes/No',1,'True/False',1,'Ideology',1, 'Race',1,'Party',1,'Education',1 + ,'Scale',1,'Agree/Disagree',1,'Oppose/Support',1,'Importance',1, 'Likelihood',1,'Certainty',1,'Satisfaction',1,'Confidence',1, + 'Effectiveness',1,'Concern',1,'Risk',1,'Threat',1,'Security',1); + my %text = ('Text',1, 'Email',1, 'Phone Number',1, 'Text Date',1, 'Currency',1); + my %slider = ('Slider',1, 'Dual Slider - Range',1, 'Multi Slider - Allocate',1); + my %dateType = ('Date',1,'Date Range',1); + my %fileUpload = ('File Upload',1); + my %hidden = ('Hidden',1); + + foreach my $q(@$questions){ + if($fileUpload{$$q{'questionType'}}){ $q->{'fileLoader'} = 1; } + elsif($text{$$q{'questionType'}}){ $q->{'textType'} = 1; } + elsif($hidden{$$q{'questionType'}}){ $q->{'hidden'} = 1; } + elsif($multipleChoice{$$q{'questionType'}}){ + $q->{'multipleChoice'} = 1; + if($$q{'maxAnswers'} > 1){ + $q->{'maxMoreOne'} = 1; + } + } + elsif($dateType{$$q{'questionType'}}){ + $q->{'dateType'} = 1; + } + elsif($slider{$$q{'questionType'}}){ + $q->{'slider'} = 1; + if($$q{'questionType'} eq 'Dual Slider - Range'){ + $q->{'dualSlider'} = 1; + $q->{'a1'} = [$q->{'answers'}->[0]]; + $q->{'a2'} = [$q->{'answers'}->[1]]; + } + } + + if($$q{'verticalDisplay'}){ $$q{'verts'} = "

    "; $$q{'verte'} = "

    "; } + } + $section->{'questions'} = $questions; + + my $out = $self->processTemplate($section,$self->get("surveyQuestionsId")); + + $self->session->http->setMimeType('application/json'); + return encode_json({"type","displayquestions","section",$section,"questions",$questions,"html",$out}); +} + + +#------------------------------------------------------------------- + +sub loadBothJSON{ + my $self = shift; + my $rId = shift; + if(defined $self->survey and defined $self->response){return;} + my $ref = $self->session->db->buildArrayRefOfHashRefs(" + select s.surveyJSON,r.responseJSON + from Survey s, Survey_response r + where s.assetId = ? and r.Survey_responseId = ?", + [$self->getId,$rId]); + $self->loadSurveyJSON($ref->[0]->{surveyJSON}); + $self->loadResponseJSON($ref->[0]->{responseJSON}, $rId); +} + +#------------------------------------------------------------------- +sub loadResponseJSON{ + my $self = shift; + my $jsonHash = shift; + my $rId = shift; + $rId = defined $rId ? $rId : $self->{responseId}; + if(defined $self->response and ! defined $rId){return;} + + + $jsonHash = $self->session->db->quickScalar("select responseJSON from Survey_response where assetId = ? and Survey_responseId = ?", + [$self->getId,$rId]) if(! defined $jsonHash); + + $self->{response} = WebGUI::Asset::Wobject::Survey::ResponseJSON->new($jsonHash,$self->session->errorHandler, $self->survey); +} + +#------------------------------------------------------------------- +sub saveResponseJSON{ + my $self = shift; + + my $data = $self->response->freeze(); + + + $self->session->db->write("update Survey_response set responseJSON = ? where Survey_responseId = ?",[$data,$self->{responseId}]); +} + + + + +#------------------------------------------------------------------- +sub response{ + my $self = shift; + return $self->{response}; +} + + +#------------------------------------------------------------------- + +sub getResponseId{ + my $self = shift; + + return $self->{responseId} if(defined $self->{responseId}); + + my $ip = $self->session->env->getIp; + my $id = $self->session->user->userId(); + my $anonId = $self->session->form->process("userid") || $self->session->http->getCookies->{"Survey2AnonId"} || undef; + $self->session->http->setCookie("Survey2AnonId",$anonId) if($anonId); + +$self->log("here"); + my $responseId; + + my $string; + + #if there is an anonid or id is for a WG user + if($anonId or $id != 1){ + $string = 'userId'; + if($anonId){ + $string = 'anonId'; + $id = $anonId; + } + $responseId = $self->session->db->quickScalar("select Survey_responseId from Survey_response where $string = ? and assetId = ? and isComplete = 0", + [$id,$self->getId()]); + + }elsif($id == 1){ + $responseId = $self->session->db->quickScalar("select Survey_responseId from Survey_response where userId = ? and ipAddress = ? and assetId = ? and isComplete = 0", + [$id,$ip,$self->getId()]); + } + + if(! $responseId){ +$self->log("no response id"); + my $allowedTakes = $self->session->db->quickScalar("select maxResponsesPerUser from Survey where assetId = ? order by revisionDate desc limit 1",[$self->getId()]); + my $haveTaken; + + if($id == 1 ){ + $haveTaken = $self->session->db->quickScalar("select count(*) from Survey_response where userId = ? and ipAddress = ? and assetId = ?", + [$id,$ip,$self->getId()]); + }else{ + $haveTaken = $self->session->db->quickScalar("select count(*) from Survey_response where $string = ? and assetId = ?", + [$id,$self->getId()]); + } + + if($haveTaken < $allowedTakes){ +$self->log("creating new response"); + $responseId = $self->session->db->setRow("Survey_response","Survey_responseId",{ + Survey_responseId=>"new", + userId=>$id, + ipAddress=>$ip, + username=>$self->session->user->username, + startDate=>WebGUI::DateTime->now->toDatabase, + endDate=>WebGUI::DateTime->now->toDatabase, + assetId=>$self->getId(), + anonId=>$anonId + }); +$self->log("1"); + $self->loadBothJSON($responseId); +$self->log("2"); + $self->response->createSurveyOrder(); +$self->log("3"); + $self->{responseId} = $responseId; +$self->log("4"); + $self->saveResponseJSON(); +$self->log("loaded nad saved survey and response"); + }else{ + } + } + $self->{responseId} = $responseId; + $self->loadBothJSON($responseId); + return $responseId; +} + + +#------------------------------------------------------------------- + +sub canTakeSurvey{ + my $self = shift; + + return $self->{canTake} if(defined $self->{canTake}); + + + if(!$self->session->user->isInGroup($self->get("groupToTakeSurvey"))){ + return 0; + } + + #Does user have too many finished survey responses + my $maxTakes = $self->getValue("maxResponsesPerUser"); + my $ip = $self->session->env->getIp; + my $id = $self->session->user->userId(); + my $takenCount = 0; + + + if($id == 1){ + $takenCount = $self->session->db->quickScalar("select count(*) from Survey_response where userId = ? and ipAddress = ? and assetId = ? + and isComplete = ?",[$id,$ip,$self->getId(),1]); + }else{ + $takenCount = $self->session->db->quickScalar("select count(*) from Survey_response where userId = ? and assetId = ? and isComplete = ?",[$id,$self->getId(),1]); + } + + + if($takenCount >= $maxTakes){ + $self->{canTake} = 0; + }else{ + $self->{canTake} = 1; + } + return $self->{canTake}; + +} + +#------------------------------------------------------------------- +sub www_viewReports { + my $self = shift; + $self->loadTempReportTable(); return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); - my $filename = $self->session->url->escape($self->get("title")."_answers.tab"); - my $content = $self->session->db->quickTab("select * from Survey_answer where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); + my $filename = $self->session->url->escape($self->get("title")."_results.tab"); + my $content = $self->session->db->quickTab("select * from Survey_tempReport t where t.assetId=? order by t.Survey_responseId, t.order",[$self->getId()]); return $self->export($filename,$content); } #------------------------------------------------------------------- -sub export{ +sub export{ my $self = shift; my $filename = shift; $filename =~ s/[^\w\d\.]/_/g; @@ -1137,7 +969,7 @@ sub export{ my $tmpDir = $store->getPath(); my $filepath = $store->getPath($filename); unless (open TEMP, ">$filepath") { - return "Error - Could not open temporary file for writing. Please use the back button and try again"; + return "Error - Could not open temporary file for writing. Please use the back button and try again"; } print TEMP $content; close TEMP; @@ -1148,303 +980,35 @@ sub export{ return undef; } -#------------------------------------------------------------------- -sub www_exportComposite { - my $self = shift; - return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); - my $filename = $self->session->url->escape($self->get("title")."_composite.tab"); - my $content = $self->session->db->quickTab("select b.question, c.response, a.userId, a.username, a.ipAddress, c.comment, c.dateOfResponse from Survey_response a - left join Survey_questionResponse c on a.Survey_responseId=c.Survey_responseId - left join Survey_question b on c.Survey_questionId=b.Survey_questionId - where a.Survey_id=".$self->session->db->quote($self->get("Survey_id"))." order by a.userId, a.ipAddress, b.sequenceNumber"); +sub loadTempReportTable{ + my $self = shift; - return $self->export($filename,$content); -} - -#------------------------------------------------------------------- -sub www_exportQuestions { - my $self = shift; - return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); - my $filename = $self->session->url->escape($self->get("title")."_questions.tab"); - my $content = $self->session->db->quickTab("select * from Survey_question where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); - return $self->export($filename,$content); -} - -#------------------------------------------------------------------- -sub www_exportResponses { - my $self = shift; - return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); - my $filename = $self->session->url->escape($self->get("title")."_responses.tab"); - my $content = $self->session->db->quickTab("select * from Survey_response where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); - return $self->export($filename,$content); -} - -#------------------------------------------------------------------- -sub www_moveAnswerDown { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - $self->moveCollateralDown("Survey_answer","Survey_answerId",$self->session->form->process("aid"),"Survey_id"); - return $self->www_editQuestion; -} - -#------------------------------------------------------------------- -sub www_moveAnswerUp { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - $self->moveCollateralUp("Survey_answer","Survey_answerId",$self->session->form->process("aid"),"Survey_id"); - return $self->www_editQuestion; -} - -#------------------------------------------------------------------- -sub www_moveQuestionDown { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - $self->moveCollateralDown("Survey_question","Survey_questionId",$self->session->form->process("qid"),"Survey_id"); - return ""; -} - -#------------------------------------------------------------------- -sub www_moveQuestionUp { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - $self->moveCollateralUp("Survey_question","Survey_questionId",$self->session->form->process("qid"),"Survey_id"); - return ""; -} - -#------------------------------------------------------------------- -sub www_moveSectionDown { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - $self->moveCollateralDown("Survey_section","Survey_sectionId",$self->session->form->process("sid"),"Survey_id"); - return ""; -} - -#------------------------------------------------------------------- -sub www_moveSectionUp { - my $self = shift; - return $self->session->privilege->insufficient() unless ($self->canEdit); - $self->moveCollateralUp("Survey_section","Survey_sectionId",$self->session->form->process("sid"),"Survey_id"); - return ""; -} - -#------------------------------------------------------------------- -sub www_respond { - my $self = shift; - return "" unless ($self->session->user->isInGroup($self->get("groupToTakeSurvey"))); - #If user has not responded before, create the responseId binding the survey to this session: fdillon 7-11-07 - my $responseCount = $self->getResponseCount; - my $responseId = $self->getResponseId; - my $canRespond = ($responseCount < $self->get("maxResponsesPerUser")); - if ($canRespond && (!defined $responseId || $self->session->form->param('responseId') eq 'new')) { - $self->generateResponseId; + $self->loadSurveyJSON(); + my $refs = $self->session->db->buildArrayRefOfHashRefs("select * from Survey_response where assetId = ?",[$self->getId()]); + $self->session->db->write("delete from Survey_tempReport where assetId = ?",[$self->getId()]); + for my $ref(@$refs){ + $self->loadResponseJSON(undef,$ref->{Survey_responseId}); + my $count = 1; + for my $q(@{$self->response->returnResponseForReporting()}){ + if(@{$q->{answers}} == 0 and $q->{comment} =~ /\w/){ + $self->session->db->write("insert into Survey_tempReport VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + [$self->getId(),$ref->{Survey_responseId}, $count++, $q->{section},$q->{sectionName},$q->{question},$q->{questionName}, + $q->{questionComment},undef,undef,undef,undef,undef,undef,undef]); + next; + } + for my $a(@{$q->{answers}}){ + $self->session->db->write("insert into Survey_tempReport VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + [$self->getId(),$ref->{Survey_responseId}, $count++, $q->{section},$q->{sectionName},$q->{question},$q->{questionName}, + $q->{questionComment},$a->{id},$a->{value},$a->{comment},$a->{time},$a->{isCorrect},$a->{value},undef]); + } + } } - - my $varname = $self->getResponseIdString; - return "" unless ($self->session->scratch->get($varname)); - my $userId = ($self->get("anonymous")) ? substr(md5_hex($self->session->user->userId),0,8) : $self->session->user->userId; - my $terminate = 0; - foreach my $key ($self->session->form->param) { - if ($key =~ /^answerId_(.+)$/) { - my $id = $1; - my ($previousResponse) = $self->session->db->quickArray("select count(*) from Survey_questionResponse - where Survey_answerId=".$self->session->db->quote($self->session->form->process("answerId_".$id))." and Survey_responseId=".$self->session->db->quote($self->session->scratch->get($varname))); - next if ($previousResponse); - my $answer = $self->getCollateral("Survey_answer","Survey_answerId",$self->session->form->process("answerId_".$id)); - if ($self->get("questionOrder") eq "response" && $answer->{gotoQuestion} eq "") { - $terminate = 1; - } - my $response = $self->session->form->process("textResponse_".$id) || $answer->{answer}; - $self->session->db->write("insert into Survey_questionResponse (Survey_answerId,Survey_questionId,Survey_responseId,Survey_id,comment,response,dateOfResponse) values ( - ".$self->session->db->quote($answer->{Survey_answerId}).", ".$self->session->db->quote($answer->{Survey_questionId}).", ".$self->session->db->quote($self->session->scratch->get($varname)).", ".$self->session->db->quote($answer->{Survey_id}).", - ".$self->session->db->quote($self->session->form->process("comment_".$id)).", ".$self->session->db->quote($response).", ".$self->session->datetime->time().")"); - } - } - - $responseCount = $self->getQuestionResponseCount($self->session->scratch->get($varname)); - if ($terminate || $responseCount >= $self->getValue("questionsPerResponse") || $responseCount >= $self->getQuestionCount) { - $self->session->db->setRow("Survey_response","Survey_responseId",{ - isComplete=>1, - endDate=>$self->session->datetime->time(), - Survey_responseId=>$self->session->scratch->get($varname) - }); - } - $self->logView() if ($self->session->setting->get("passiveProfilingEnabled")); - return ""; + return 1; } - - -#------------------------------------------------------------------- -sub www_viewGradebook { - my $self = shift; - return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); - $self->logView() if ($self->session->setting->get("passiveProfilingEnabled")); - my $i18n = WebGUI::International->new($self->session,'Asset_Survey'); - my $var = $self->getMenuVars; - $var->{title} = $i18n->get(71); - my $p = WebGUI::Paginator->new($self->session,$self->getUrl('func=viewGradebook')); - $p->setDataByQuery("select userId,username,ipAddress,Survey_responseId,startDate,endDate from Survey_response - where Survey_id=".$self->session->db->quote($self->get("Survey_id"))." order by username,ipAddress,startDate"); - my $users = $p->getPageData; - ($var->{'question.count'}) = $self->session->db->quickArray("select count(*) from Survey_question where Survey_id=".$self->session->db->quote($self->get("Survey_id"))); - if ($var->{'question.count'} > $self->get("questionsPerResponse")) { - $var->{'question.count'} = $self->get("questionsPerResponse"); - } - $var->{'response.user.label'} = $i18n->get(67); - $var->{'response.count.label'} = $i18n->get(52); - $var->{'response.percent.label'} = $i18n->get(54); - my @responseloop; - foreach my $user (@$users) { - my ($correctCount) = $self->session->db->quickArray("select count(*) from Survey_questionResponse a left join - Survey_answer b on a.Survey_answerId=b.Survey_answerId where a.Survey_responseId=".$self->session->db->quote($user->{Survey_responseId}) - ." and b.isCorrect=1"); - push(@responseloop, { - 'response.url'=>$self->getUrl('func=viewIndividualSurvey;responseId='.$user->{Survey_responseId}), - 'response.user.name'=>($user->{userId} eq '1') ? $user->{ipAddress} : $user->{username}, - 'response.count.correct' => $correctCount, - 'response.percent' => round(($correctCount/$var->{'question.count'})*100) - }); - } - $var->{response_loop} = \@responseloop; - $p->appendTemplateVars($var); - return $self->session->style->process($self->processTemplate($var,$self->getValue("gradebookTemplateId")),$self->getValue("styleTemplateId")); -# return $self->processTemplate($self->getValue("gradebookTemplateId"),$var,"Survey/Gradebook"); -} - - -#------------------------------------------------------------------- -sub www_viewIndividualSurvey { - my $self = shift; - return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); - $self->logView() if ($self->session->setting->get("passiveProfilingEnabled")); - my $i18n = WebGUI::International->new($self->session,'Asset_Survey'); - my $var = $self->getMenuVars; - $var->{'title'} = $i18n->get(70); - $var->{'delete.url'} = $self->getUrl('func=deleteResponse;responseId='.$self->session->form->process("responseId")); - $var->{'delete.label'} = $i18n->get(69); - my $response = $self->session->db->getRow("Survey_response","Survey_responseId",$self->session->form->process("responseId")); - $var->{'start.date.label'} = $i18n->get(76); - $var->{'start.date.epoch'} = $response->{startDate}; - $var->{'start.date.human'} =$self->session->datetime->epochToHuman($response->{startDate},"%z"); - $var->{'start.time.human'} =$self->session->datetime->epochToHuman($response->{startDate},"%Z"); - $var->{'end.date.label'} = $i18n->get(77); - $var->{'end.date.epoch'} = $response->{endDate}; - $var->{'end.date.human'} =$self->session->datetime->epochToHuman($response->{endDate},"%z"); - $var->{'end.time.human'} =$self->session->datetime->epochToHuman($response->{endDate},"%Z"); - $var->{'duration.label'} = $i18n->get(78); - $var->{'duration.minutes'} = int(($response->{end} - $response->{start})/60); - $var->{'duration.minutes.label'} = $i18n->get(79); - $var->{'duration.seconds'} = (($response->{endDate} - $response->{start})%60); - $var->{'duration.seconds.label'} = $i18n->get(80); - $var->{'answer.label'} = $i18n->get(19) if ($self->get("mode") eq "quiz"); - $var->{'response.label'} = $i18n->get(66); - $var->{'comment.label'} = $i18n->get(57); - my $questions = $self->session->db->read("select Survey_questionId,question,answerFieldType from Survey_question - where Survey_id=".$self->session->db->quote($self->get("Survey_id"))." order by sequenceNumber"); - my @questionloop; - while (my $qdata = $questions->hashRef) { - my @aid; - my @answer; - if ($qdata->{answerFieldType} eq "radioList") { - my $sth = $self->session->db->read("select Survey_answerId,answer from Survey_answer - where Survey_questionId=".$self->session->db->quote($qdata->{Survey_questionId})." and isCorrect=1 order by sequenceNumber"); - while (my $adata = $sth->hashRef) { - push(@aid,$adata->{Survey_answerId}); - push(@answer,$adata->{answer}); - } - $sth->finish; - } - my $rdata = $self->session->db->quickHashRef("select Survey_answerId,response,comment from Survey_questionResponse - where Survey_questionId=".$self->session->db->quote($qdata->{Survey_questionId})." and Survey_responseId=".$self->session->db->quote($self->session->form->process("responseId"))); - push(@questionloop,{ - question => $qdata->{question}, - 'question.id'=>$qdata->{Survey_questionId}, - 'question.isRadioList' => ($qdata->{answerFieldType} eq "radioList"), - 'question.response' => $rdata->{response}, - 'question.comment' => $rdata->{comment}, - 'question.isCorrect' => isIn($rdata->{Survey_answerId}, @aid), - 'question.answer' => join(", ",@answer), - }); - } - $questions->finish; - $var->{question_loop} = \@questionloop; - return $self->session->style->process($self->processTemplate($var, $self->getValue("responseTemplateId")),$self->getValue("styleTemplateId")); -# return $self->processTemplate($self->getValue("responseTemplateId"),$var,"Survey/Response"); -} - -#------------------------------------------------------------------- -sub www_viewStatisticalOverview { - my $self = shift; - return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); - $self->logView() if ($self->session->setting->get("passiveProfilingEnabled")); - my $var = $self->getMenuVars; - my $i18n = WebGUI::International->new($self->session,'Asset_Survey'); - $var->{title} = $i18n->get(58); - my $p = WebGUI::Paginator->new($self->session,$self->getUrl('func=viewStatisticalOverview')); - $p->setDataByQuery("select Survey_questionId,question,answerFieldType,allowComment from Survey_question - where Survey_id=".$self->session->db->quote($self->get("Survey_id"))." order by sequenceNumber"); - my $questions = $p->getPageData; - my @questionloop; - $var->{'answer.label'} = $i18n->get(19); - $var->{'response.count.label'} = $i18n->get(53); - $var->{'response.percent.label'} = $i18n->get(54); - $var->{'show.responses.label'} = $i18n->get(55); - $var->{'show.comments.label'} = $i18n->get(56); - foreach my $question (@$questions) { - my @answerloop; - my ($totalResponses) = $self->session->db->quickArray("select count(*) from Survey_questionResponse where Survey_questionId=".$self->session->db->quote($question->{Survey_questionId})); - if ($question->{answerFieldType} eq "radioList") { - my $sth = $self->session->db->read("select Survey_answerId,answer,isCorrect from Survey_answer where - Survey_questionId=".$self->session->db->quote($question->{Survey_questionId})." order by sequenceNumber"); - while (my $answer = $sth->hashRef) { - my ($numResponses) = $self->session->db->quickArray("select count(*) from Survey_questionResponse where Survey_answerId=".$self->session->db->quote($answer->{Survey_answerId})); - my $responsePercent; - if ($totalResponses) { - $responsePercent = round(($numResponses/$totalResponses)*100); - } else { - $responsePercent = 0; - } - my @commentloop; - my $sth2 = $self->session->db->read("select comment from Survey_questionResponse where Survey_answerId=".$self->session->db->quote($answer->{Survey_answerId})); - while (my ($comment) = $sth2->array) { - push(@commentloop,{ - 'answer.comment'=>$comment - }); - } - $sth2->finish; - push(@answerloop,{ - 'answer.isCorrect'=>$answer->{isCorrect}, - 'answer' => $answer->{answer}, - 'answer.response.count' =>$numResponses, - 'answer.response.percent' =>$responsePercent, - 'comment_loop'=>\@commentloop - }); - } - $sth->finish; - } else { - my $sth = $self->session->db->read("select response,comment from Survey_questionResponse where Survey_questionId=".$self->session->db->quote($question->{Survey_questionId})); - while (my $response = $sth->hashRef) { - push(@answerloop,{ - 'answer.response'=>$response->{response}, - 'answer.comment'=>$response->{comment} - }); - } - $sth->finish; - } - push(@questionloop,{ - question=>$question->{question}, - 'question.id'=>$question->{Survey_questionId}, - 'question.isRadioList' => ($question->{answerFieldType} eq "radioList"), - 'question.response.total' => $totalResponses, - 'answer_loop'=>\@answerloop, - 'question.allowComment'=>$question->{allowComment} - }); - } - $var->{question_loop} = \@questionloop; - $p->appendTemplateVars($var); - - return $self->session->style->process($self->processTemplate($var, $self->getValue("overviewTemplateId")),$self->getValue("styleTemplateId")); +sub log{ + my $self = shift; + $self->session->errorHandler->error(shift); } 1; - diff --git a/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm b/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm new file mode 100644 index 000000000..22ccc9f86 --- /dev/null +++ b/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm @@ -0,0 +1,338 @@ +package WebGUI::Asset::Wobject::Survey::ResponseJSON; + +use strict; +use JSON; +use Data::Dumper; + +sub new{ + my $class = shift; + my $json = shift; + my $log = shift; + my $survey = shift; + my $self = {}; + $self->{survey} = $survey; + $self->{log} = $log; + my $temp = decode_json($json) if defined $json; + $self->{surveyOrder} = defined $temp->{surveyOrder} ? $temp->{surveyOrder} : [];#an array of question addresses, with the third member being an array of answers + $self->{responses} = defined $temp->{responses} ? $temp->{responses} : {}; + $self->{lastResponse} = defined $temp->{lastResponse} ? $temp->{lastResponse} : -1; + bless($self,$class); + return $self; +} + +#---------------------------------------------------------------------------- + +=head2 createSurveyOrder ( SurveyJSON, [address,address] ) + +This creates the order for the survey which will change after every fork. +The survey order is to precreate random questions and answers, which also leaves a record or what the user was presented with. +Forks are passed in to show where to branch the new order. + +=cut + +sub createSurveyOrder{ + my $self = shift; + my $order; + my $qstarting = 0; +$self->log('wtf am I faling for'); + for(my $s = 0; $s <= $#{$self->survey->sections()}; $s++){ + #create question order for section + my @qorder; + if($self->survey->section([$s])->{randomizeQuestions}){ + @qorder = shuffle(($qstarting .. $#{$self->survey->questions([$s])})); + }else{ + @qorder = (($qstarting .. $#{$self->survey->questions([$s])})); + } + + #if this is an empty section, make sure it is still on the list to be seen + if(@qorder == 0){ + push(@$order,[$s]); + } + $qstarting = 0; + #create answer order for question + for (@qorder){ + my @aorder; + if($self->survey->question([$s,$_])->{randomizeAnswers}){ + @aorder = shuffle(($qstarting .. $#{$self->survey->question([$s,$_])->{answers}})); + }else{ + @aorder = (($qstarting .. $#{$self->survey->question([$s,$_])->{answers}})); + } + push(@$order,[$s,$_,\@aorder]); + } + } + $self->{surveyOrder} = $order; +} +sub shuffle { + my @a = splice @_; + for my $i (0 .. $#a) { + my $j = int rand @a; + @a[$i, $j] = @a[$j, $i]; + } + return @a; +} + +sub freeze{ + my $self = shift; + my %temp = %{$self}; + delete $temp{log}; + delete $temp{survey}; + return encode_json(\%temp); +} + +#the index of the last surveyOrder entry shown +sub lastResponse{ + my $self = shift; + my $res = shift; + if(defined $res){ + $self->{lastResponse} = $res; + }else{ + return $self->{lastResponse}; + } +} +#array of addresses in which the survey should be presented +sub surveyOrder{ + my $self = shift; + return $self->{surveyOrder}; +} + + +sub nextSectionId{ + my $self = shift; + return $self->surveyOrder->[$self->lastResponse + 1]->[0]; +} + + +sub nextSection{ + my $self = shift; + return $self->survey->section([$self->surveyOrder->[$self->lastResponse + 1]->[0]]); +} +sub currentSection{ + my $self = shift; + return $self->survey->section([$self->surveyOrder->[$self->lastResponse]->[0]]); +} + +sub recordResponses{ + my $self = shift; + my $responses = shift; + my $session = shift; + + my %mcTypes = ('Agree/Disagree',1,'Certainty',1,'Concern',1,'Confidence',1,'Education',1,'Effectiveness',1,'Gender',1,'Ideology',1,'Importance',1, + 'Likelihood',1,'Party',1,'Multiple Choice',1,'Oppose/Support',1,'Race',1,'Risk',1,'Satisfaction',1,'Scale',1,'Security',1, + 'Threat',1,'True/False',1,'Yes/No',1); + my %sliderTypes = ('Dual Slider - Range',1,'Multi Slider - Allocate',1,'Slider',1); + my %textTypes = ('Currency','Email',1,'Phone Number',1,'Text',1,'Text Date',1); + my %fileTypes = ('File Upload',1); + my %dateTypes = ('Date','Date Range',1); + my %hiddenTypes = ('Hidden',1); + #These were just submitted from the user, so we need to see what and how they were (un)answered. + my $questions = $self->nextQuestions(); + my $qAnswered = 1; + my $terminal = 0; + my $terminalUrl; + my $goto; + #my $section = $self->survey->section([$questions->[0]->{sid}]); + my $section = $self->currentSection(); + if($section->{terminal}){ + $terminal = 1; + $terminalUrl = $section->{terminalUrl}; + } + + #There were no questions in the section just displayed, so increment the lastResponse by one + if(ref $questions ne 'ARRAY'){ + $self->lastResponse($self->lastResponse + 1); + #$self->log("Incrementing last response by one"); + return [$terminal,$terminalUrl]; + } +#$self->log("There are questions to be submitted in this section"); + + for my $question(@$questions){ + my $aAnswered = 0; + if($question->{terminal}){ + $terminal = 1; + $terminalUrl = $question->{terminalUrl}; + } + $self->responses->{$question->{id}}->{comment} = $responses->{$question->{id}."comment"}; + for my $answer(@{$question->{answers}}){ + + if(defined($responses->{$answer->{id}}) and $responses->{$answer->{id}} =~ /\S/){ + + $aAnswered = 1; + if($mcTypes{$question->{questionType}}){ + $self->responses->{$answer->{id}}->{value} = $answer->{recordedAnswer}; +#$self->log("Recorded Answer ".$answer->{recordedAnswer}); + } + else{ +#$self->log("Returned Answer ".$responses->{$answer->{id}}); + $self->responses->{$answer->{id}}->{value} = $responses->{$answer->{id}}; + } + $self->responses->{$answer->{id}}->{'time'} = time(); + $self->responses->{$answer->{id}}->{comment} = $responses->{$answer->{id}."comment"}; + + if($answer->{terminal}){ + $terminal = 1; + $terminalUrl = $answer->{terminalUrl}; + } + elsif($answer->{goto} =~ /\w/){ + $goto = $answer->{goto}; + } + } + } + $qAnswered = 0 if(!$aAnswered and $question->{required}); + } + + #if all responses completed, move the lastResponse index to the last question shown + if($qAnswered){ + $self->lastResponse($self->lastResponse + @$questions); + $self->goto($goto) if(defined $goto); + }else{ + $terminal = 0; + } + return [$terminal,$terminalUrl]; +} +sub goto{ + my $self = shift; + my $goto = shift; +#$self->log("In goto for '$goto'"); + for(my $i = 0; $i <= $#{$self->surveyOrder()}; $i++){ + my $section = $self->survey->section($self->surveyOrder()->[$i]); + my $question = $self->survey->question($self->surveyOrder()->[$i]); + if(ref $section eq 'HASH' and $section->{variable} eq $goto){ +#$self->log("setting lastResponse to section ".($i-1)); + $self->lastResponse($i - 1); + last; + } + if(ref $question eq 'HASH' and $question->{variable} eq $goto){ +#$self->log("setting lastResponse to question ".($i-1)); + $self->lastResponse($i - 1); + last; + } + } +} +sub getPreviousAnswer{ + my $self = shift; + my $questionParam = shift; + for my $q (@{$self->surveyOrder}){ + my $question = $self->survey->question([$$q[0],$$q[1]]); + if($question->{variable} eq $questionParam){ + for (0 .. @{$self->survey->answers([$$q[0],$$q[1]])}){ + if(exists $self->responses->{$$q[0]."-".$$q[1]."-".$_}){ + return $self->responses->{$$q[0]."-".$$q[1]."-".$_}->{value}; + } + } + } + } +} + +sub nextQuestions{ + my $self = shift; +#$self->log("In nextQuestions"); + + if($self->lastResponse >= $#{$self->surveyOrder}){ + return []; + } + + my $nextSectionId = $self->nextSectionId; + +#$self->log("next sectionid is $nextSectionId"); + + my $qPerPage = $self->survey->section([$self->nextSectionId])->{questionsPerPage}; + + + #load Previous answer text + my $section = $self->nextSection(); +#$self->log("Section text is ".$section->{text}); + $section->{'text'} =~ s/\[\[([^\%]*?)\]\]/$self->getPreviousAnswer($1)/eg; + +#$self->log("qperpage $qPerPage"); + + my $questions; + for(my $i = 1; $i <= $qPerPage; $i++){ + my $qAddy = $self->surveyOrder->[$self->lastResponse + $i]; +#$self->log("qAddy was $$qAddy[0]-$$qAddy[1]"); + next if(! exists $$qAddy[1]);#skip this if it doesn't have a question (for sections with no questions) + + if($$qAddy[0] != $nextSectionId){ +#$self->log("Next question section did not match current section"); + last; + } +#$self->log("wtf"); + my %question = %{$self->survey->question([$$qAddy[0],$$qAddy[1]])}; + $question{'text'} =~ s/\[\[([^\%]*?)\]\]/$self->getPreviousAnswer($1)/eg; + delete $question{answers}; + $question{id} = "$$qAddy[0]-$$qAddy[1]"; + $question{sid} = "$$qAddy[0]"; + for (@{$$qAddy[2]}){ + my $ans = $self->survey->answer([$$qAddy[0],$$qAddy[1],$_]); + $ans->{'text'} =~ s/\[\[([^\%]*?)\]\]/$self->getPreviousAnswer($1)/eg; + $ans->{id} = "$$qAddy[0]-$$qAddy[1]-$_"; + push(@{$question{answers}},$ans); + } + push(@$questions,\%question); + } +#$self->log("Next Questions returning with "); + return $questions +} + +sub surveyEnd{ + my $self = shift; +#$self->log("LR is ".$self->lastResponse." and order is ".$#{$self->surveyOrder}); +#$self->log("ENDING THE SURVEY\n\n\n") if($self->lastResponse > $#{$self->surveyOrder}); + return 1 if($self->lastResponse >= $#{$self->surveyOrder}); + return 0; +} + +sub returnResponseForReporting{ + my $self = shift; + my @responses = (); + for my $entry(@{$self->surveyOrder}){ + if(@$entry == 1){ + next; + } + my @answers; + for (@{$$entry[2]}){ + if(defined $self->responses->{"$$entry[0]-$$entry[1]-$_"}){ + $self->responses->{"$$entry[0]-$$entry[1]-$_"}->{id} = $_; + if($self->survey->answer([$$entry[0],$$entry[1],$_])->{isCorrect}){ + my $value; + if($self->survey->answer([$$entry[0],$$entry[1],$_])->{value} =~ /\w/){ + $value = $self->survey->answer([$$entry[0],$$entry[1],$_])->{value}; + }else{ + $value = $self->survey->question([$$entry[0],$$entry[1]])->{value}; + } + $self->responses->{"$$entry[0]-$$entry[1]-$_"}->{value} = $value; + $self->responses->{"$$entry[0]-$$entry[1]-$_"}->{isCorrect} = 1; + }else{ + $self->responses->{"$$entry[0]-$$entry[1]-$_"}->{isCorrect} = 0; + } + push(@answers,($self->responses->{"$$entry[0]-$$entry[1]-$_"})); + } + } + push(@responses,({'section',$$entry[0],'question',$$entry[1], + 'sectionName',$self->survey->section([$$entry[0]])->{variable}, + 'questionName',$self->survey->question([$$entry[0],$$entry[1]])->{variable}, + 'questionComment',$self->responses->{"$$entry[0]-$$entry[1]"}->{comment}, + 'answers',\@answers})); + } +#$self->log(Dumper @responses); + return \@responses; +} + +#the actual responses to the survey. A response is for a question and is accessed by the exact same address as a survey member. +#Questions only contain the comment and an array of answer Responses. +#Answers only contain, entered text, entered verbatim, their index in the Survey Question Answer array, and the assetId to the uploaded file. +sub responses{ + my $self = shift; + return $self->{responses}; +} + +sub survey{ + my $self = shift; + return $self->{survey}; +} +sub log{ + my ($self,$message) = @_; + if(defined $self->{log}){ + $self->{log}->error($message); + } +} +1; diff --git a/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm b/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm new file mode 100644 index 000000000..9e54a379c --- /dev/null +++ b/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm @@ -0,0 +1,446 @@ +package WebGUI::Asset::Wobject::Survey::SurveyJSON; + +use strict; +use JSON; +use Data::Dumper; + +sub new{ + my $class = shift; + my $json = shift; + my $log = shift; + my $self = {}; + $self->{log} = $log; + my $temp = decode_json($json) if defined $json; + $self->{sections} = defined $temp->{sections} ? $temp->{sections} : []; + $self->{survey} = defined $temp->{survey} ? $temp->{survey} : {}; + bless($self,$class); + if(@{$self->sections} == 0){ + $self->newObject([]); + } + return $self; +} +sub freeze{ + my $self = shift; + my %temp; + $temp{sections} = $self->{sections}; + $temp{survey} = $self->{survey}; + return encode_json(\%temp); +} +sub newObject{ + my $self = shift; + my $address = shift; + if(@$address == 0){ + push(@{$self->sections}, $self->newSection()); + return [$#{$self->sections}]; + }elsif(@$address == 1){ + push( @{$self->questions($address)}, $self->newQuestion($address)); + $$address[1] = $#{$self->questions($address)}; + return $address; + }elsif(@$address == 2){ + push(@{$self->answers($address)}, $self->newAnswer($address)); + $$address[2] = $#{$self->answers($address)}; + return $address; + } +} + +#address is the array of objects currently selected in the edit screen +#data is the array of hash items for displaying +sub getDragDropList{ + my $self = shift; + my $address = shift; + my @data; +#$self->log("dd'ing sections".$#{$self->sections}); +eval{ + for(my $i = 0; $i <= $#{$self->sections}; $i++){ + push(@data,{text=>$self->section([$i])->{title}, type=>'section'}); + if($address->[0] == $i){ + + for(my $x = 0; $x <= $#{$self->questions($address)}; $x++){ +##$self->log("dd'ing questions".$#{$self->questions}); + push(@data,{text=>$self->question([$i,$x])->{text}, type=>'question'}); + if($address->[1] == $x){ + for(my $y = 0; $y <= $#{$self->answers($address)}; $y++){ +##$self->log("dd'ing answers".$#{$self->answers}); + push(@data,{text=>$self->answer([$i,$x,$y])->{text}, type=>'answer'}); + } + } + } + } + } +}; +#$self->log($@); +##$self->log('finished dding'); + return \@data; +} + +sub getObject{ + my ($self,$address) = @_; + if(@$address == 1){ + return $self->{sections}->[$address->[0]]; + }elsif(@$address == 2){ + return $self->{sections}->[$address->[0]]->{questions}->[$address->[1]]; + }else{ + return $self->{sections}->[$address->[0]]->{questions}->[$address->[1]]->{answers}->[$address->[2]]; + } +} + +sub getEditVars{ + my ($self,$address) = @_; + + if(@$address == 1){ + return $self->getSectionEditVars($address); + }elsif(@$address == 2){ + return $self->getQuestionEditVars($address); + }elsif(@$address == 3){ + return $self->getAnswerEditVars($address); + } +} +sub getSectionEditVars{ + my $self = shift; + my $address = shift; + my $object = $self->section($address); + my %var = %{$object}; + $var{id} = $address->[0]; + $var{displayed_id} = $address->[0]+1; + delete $var{questions}; + delete $var{questionsPerPage}; + for(1 .. 20){ +# if($_ == $self->section($address)->{questionsPerPage}){ + if($_ == $object->{questionsPerPage}){ + push(@{$var{questionsPerPage}},{'index',$_,'selected',1}); + }else{ + push(@{$var{questionsPerPage}},{'index',$_,'selected',0}); + } + } + return \%var; +} +sub getQuestionEditVars{ + my $self = shift; + my $address = shift; + my $object = $self->question($address); + my %var = %{$object}; + $var{id} = $address->[0]."-".$address->[1]; + $var{displayed_id} = $address->[1]+1; + delete $var{answers}; + delete $var{questionType}; + my @types = ('Agree/Disagree','Certainty','Concern','Confidence','Currency','Date','Date Range','Dual Slider - Range','Education','Effectiveness', + 'Email','File Upload','Gender','Hidden','Ideology','Importance','Likelihood','Multi Slider - Allocate','Multiple Choice','Oppose/Support', + 'Party','Phone Number','Race','Risk','Satisfaction','Scale','Security','Slider','Text','Text Date','Threat','True/False','Yes/No'); + for(@types){ + if($_ eq $object->{questionType}){ + push(@{$var{questionType}},{'text',$_,'selected',1}); + }else{ + push(@{$var{questionType}},{'text',$_,'selected',0}); + } + } + return \%var; +} +sub getAnswerEditVars{ + my $self = shift; + my $address = shift; + my $object = $self->answer($address); + my %var = %{$object}; + $var{id} = $address->[0]."-".$address->[1]."-".$address->[2]; + $var{displayed_id} = $address->[2]+1; + return \%var; +} + +sub update{ + my ($self,$address,$ref) = @_; + my $object; + my $newQuestion = 0; + if(@$address == 1){ +#$self->log("A section"); + $object = $self->section($address); + if(! defined $object){ + $object = $self->newSection(); + push(@{$self->sections},$object); + } + }elsif(@$address == 2){ +#$self->log("A question"); + $object = $self->question($address); + if(! defined $object){ + my $newQuestion = 1; + $object = $self->newQuestion(); + push(@{$self->questions($address)},$object); + } + }elsif(@$address == 3){ +#$self->log("A answer"); + $object = $self->answer($address); + if(! defined $object){ + $object = $self->newAnswer(); + push(@{$self->answers($address)},$object); + } + } + if(@$address == 2 and ! $newQuestion){ + if($ref->{questionType} ne $self->question($address)->{questionType}){ + $self->updateQuestionAnswers($address,$ref->{questionType}); + } + } + for my $key(keys %$object){ +#$self->log("$key $$object{$key}"); + $object->{$key} = $ref->{$key} if(defined $$ref{$key}); + } +} + + +#determine what to add and add it. +# ref should contain all the information for the new +sub insertObject{ + my ($self,$object,$address) = @_; +#$self->log("Inserting ".join(',',@$address)); + if(@$address == 1){ + splice(@{$self->sections($address)},$$address[0] + 1, 0, $object); + }elsif(@$address == 2){ + splice(@{$self->questions($address)},$$address[1] + 1, 0, $object); + }elsif(@$address == 3){ + splice(@{$self->answers($address)},$$address[2] + 1, 0, $object); + } +#$self->log("Finished inserting "); + +} + +sub copy{ + my ($self,$address) = @_; + if(@$address == 1){ + my %newSection = %{$self->section($address)}; + push(@{$self->sections}, \%newSection); + return [$#{$self->sections}]; +#$self->log("copying here $$address[0] :".$#{$self->sections}); + }elsif(@$address == 2){ +#$self->log("copying question $$address[0] $$address[1]"); + my %newQuestion = %{$self->question($address)}; + push( @{$self->questions($address)}, \%newQuestion); + $$address[1] = $#{$self->questions($address)}; +#$self->log("to $$address[0] $$address[1]"); + return $address; + } +} + + +sub remove{ + my ($self,$address,$movingOverride) = @_; + if(@$address == 1){ +#$self->log("removing here $$address[0] :".$#{$self->sections}) if($$address[0] != 0 or defined $movingOverride);; + splice(@{$self->{sections}},$$address[0],1) if($$address[0] != 0 or defined $movingOverride);#can't delete the first section +#$self->log("removing here $$address[0] :".$#{$self->sections}); + }elsif(@$address == 2){ +#$self->log("removing here $$address[0] $$address[1]"); + splice(@{$self->questions($address)},$$address[1],1); + }elsif(@$address == 3){ +#$self->log("removing here $$address[0] $$address[1] $$address[2]"); + splice(@{$self->answers($address)},$$address[2],1); + } +} + +sub newSection{ + my %members = ( + 'text', '', + 'title', 'NEW SECTION', + 'variable', '', + 'questionsPerPage', 5, + 'questionsOnSectionPage', 1, + 'randomizeQuestions', 0, + 'everyPageTitle', 1, + 'everyPageText', 1, + 'terminal', 0, + 'terminalUrl', '', + 'goto', '', + 'timeLimit', 0, + 'type','section' + ); + $members{questions} = []; + return \%members; +} +sub newQuestion{ + my %members = ( + 'text', '', + 'variable','', + 'allowComment',0, + 'commentCols',10, + 'commentRows',5, + 'randomizeAnswers',0, + 'questionType','Multiple Choice', + 'randomWords','', + 'verticalDisplay',0, + 'required',0, + 'maxAnswers',1, + 'value',1, + 'textInButton',0, +# 'terminal',0, +# 'terminalUrl','', + 'type','question' + ); + $members{answers} = []; + return \%members; +} +sub newAnswer{ + my %members = ( + 'text', '', + 'verbatim',0, + 'textCols',10, + 'textRows',5, + 'goto','', + 'recordedAnswer','', + 'isCorrect',1, + 'min',1, + 'max',10, + 'step',1, + 'value',1, + 'terminal',0, + 'terminalUrl','', + 'type','answer' + ); + return \%members; +} + +sub updateQuestionAnswers{ + my $self = shift; + my $address = shift; + my $type = shift; + +#$self->log("In updateQuestion"); + + my @addy = @{$address}; + my $question = $self->question($address); + $question->{answers} = []; + + if($type eq 'Date Range' or $type eq 'Multi Slider - Allocate' or $type eq 'Dual Slider - Range'){ + push(@{$question->{answers}},$self->newAnswer()); + push(@{$question->{answers}},$self->newAnswer()); + }elsif($type eq 'Currency'){ + push(@{$question->{answers}},$self->newAnswer()); + $addy[2] = 0; + $self->update(\@addy,{'text','Currency Amount'}); + }elsif($type eq 'Text Date'){ + push(@{$question->{answers}},$self->newAnswer()); + $addy[2] = 0; + $self->update(\@addy,{'text','Date:'}); + }elsif($type eq 'Phone Number'){ + push(@{$question->{answers}},$self->newAnswer()); + $addy[2] = 0; + $self->update(\@addy,{'text','Phone Number:'}); + }elsif($type eq 'Email'){ + push(@{$question->{answers}},$self->newAnswer()); + $addy[2] = 0; + $self->update(\@addy,{'text','Email:'}); + }elsif($type eq 'Education'){ + my @ans = ('Elementary or some high school','High school/GED','Some college/vocational school','College graduate', + 'Some graduate work','Master\'s degree','Doctorate (of any type)','Other degree (verbatim)'); + $self->addAnswersToQuestion(\@addy,\@ans,{7,1}); + }elsif($type eq 'Party'){ + my @ans = ('Democratic party','Republican party (or GOP)','Independant party','Other party (verbatim)'); + $self->addAnswersToQuestion(\@addy,\@ans,{3,1}); + }elsif($type eq 'Race'){ + my @ans = ('American Indian','Asian','Black','Hispanic','White non-Hispanic','Something else (verbatim)'); + $self->addAnswersToQuestion(\@addy,\@ans,{5,1}); + }elsif($type eq 'Ideology'){ + my @ans = ('Strongly liberal','Liberal','Somewhat liberal','Middle of the road','Slightly conservative','Conservative','Strongly conservative'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Security'){ + my @ans = ('Not at all secure','','','','','','','','','','Extremely secure'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Threat'){ + my @ans = ('No threat','','','','','','','','','','Extreme threat'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Risk'){ + my @ans = ('No risk','','','','','','','','','','Extreme risk'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Concern'){ + my @ans = ('Not at all concerned','','','','','','','','','','Extremely concerned'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Effectiveness'){ + my @ans = ('Not at all effective','','','','','','','','','','Extremely effective'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Confidence'){ + my @ans = ('Not at all confident','','','','','','','','','','Extremely confident'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Satisfaction'){ + my @ans = ('Not at all satisfied','','','','','','','','','','Extremely satisfied'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Certainty'){ + my @ans = ('Not at all certain','','','','','','','','','','Extremely certain'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Likelihood'){ + my @ans = ('Not at all likely','','','','','','','','','','Extremely likely'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Importance'){ + my @ans = ('Not at all important','','','','','','','','','','Extremely important'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Oppose/Support'){ + my @ans = ('Strongly oppose','','','','','','Strongly Support'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Agree/Disagree'){ + my @ans = ('Strongly disagree','','','','','','Strongly agree'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'True/False'){ + my @ans = ('True','False'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Yes/No'){ + my @ans = ('Yes','No'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }elsif($type eq 'Gender'){ + my @ans = ('Male','Female'); + $self->addAnswersToQuestion(\@addy,\@ans,{}); + }else{ + push(@{$question->{answers}},$self->newAnswer()); + } +} +sub addAnswersToQuestion{ + my $self = shift; + my $addy = shift; + my $ans = shift; + my $verbs = shift; +#$self->log(Dumper $verbs); + for(0 .. $#$ans){ + push(@{$self->question($addy)->{answers}},$self->newAnswer()); + $$addy[2] = $_; +#$self->log("$_:".defined $$verbs{$_}." ".$$verbs{$_}); + if(defined $$verbs{$_} and $_ == $$verbs{$_}){ + $self->update($addy,{'text',$$ans[$_],'recordedAnswer',$_+1,'verbatim',1}); + }else{ + $self->update($addy,{'text',$$ans[$_],'recordedAnswer',$_+1}); + } + } +} + + +#------------------------------ +#accessors and helpers +#------------------------------ +sub sections{ + my $self = shift; + return $self->{sections}; +} +sub section{ + my $self = shift; + my $address = shift; + return $self->{sections}->[$$address[0]]; +} +sub questions{ + my $self = shift; + my $address = shift; + return $self->{sections}->[$$address[0]]->{questions}; +} +sub question{ + my $self = shift; + my $address = shift; + return $self->{sections}->[$$address[0]]->{questions}->[$$address[1]]; +} +sub answers{ + my $self = shift; + my $address = shift; + return $self->{sections}->[$$address[0]]->{questions}->[$$address[1]]->{answers}; +} +sub answer{ + my $self = shift; + my $address = shift; + return $self->{sections}->[$$address[0]]->{questions}->[$$address[1]]->{answers}->[$$address[2]]; +} +sub log{ + my ($self,$message) = @_; + if(defined $self->{log}){ + $self->{log}->error($message); + } +} +1; diff --git a/lib/WebGUI/i18n/English/Asset_Survey.pm b/lib/WebGUI/i18n/English/Asset_Survey.pm index 278eccc19..7b7e795a0 100644 --- a/lib/WebGUI/i18n/English/Asset_Survey.pm +++ b/lib/WebGUI/i18n/English/Asset_Survey.pm @@ -3,1269 +3,226 @@ use strict; our $I18N = { - '100' => { - message => q|Add a HTML Area Answer|, - lastUpdated => 1122296097 - }, - - '101' => { - message => q|Add a Text Area Answer|, - lastUpdated => 1122296097 - }, - - '102' => { - message => q|Section Name|, - lastUpdated => 1122296097 - }, - - '103' => { - message => q|Survey Section, Add/Edit|, - lastUpdated => 1122296097 - }, - - '104' => { - message => q|Add a new section|, - lastUpdated => 1122296097 - }, - - '105' => { - message => q|Are you sure you wish to delete this section?|, - lastUpdated => 1122296097 - }, - - '106' => { - message => q|Section|, - lastUpdated => 1122296097 - }, - - '106 description' => { - message => q|Which section should this question be added to?|, - lastUpdated => 1122296097 - }, - - '107' => { - message => q|None|, - lastUpdated => 1122296097 - }, - - - '32' => { - message => q|False|, - lastUpdated => 1037498832 - }, - - - '33' => { - message => q|Strongly Agree|, - lastUpdated => 1037498857 - }, - - '21' => { - message => q|Go To|, - lastUpdated => 1035506057 - }, - - '90' => { - message => q|Survey Template Common Vars|, - lastUpdated => 1078223067 - }, - - '63' => { - message => q|Export questions.|, - lastUpdated => 1037556710 - }, - - '71' => { - message => q|Grade Book|, - lastUpdated => 1037573252 - }, - - '7' => { - message => q|Response Driven|, - lastUpdated => 1033944729 - }, - - '26' => { - message => q|Add a frequency (always/never) answer scale.|, - lastUpdated => 1035947924 - }, - - '80' => { - message => q|seconds|, - lastUpdated => 1038789602 - }, - - '18' => { - message => q|Edit Answer|, - lastUpdated => 1035436102 - }, - - '72' => { - message => q|Are you certain you wish to delete this user's responses?|, - lastUpdated => 1037573460 - }, - - '16' => { - message => q|Randomize answers?|, - lastUpdated => 1035429242 - }, - - '44' => { - message => q|Are you certain you wish to delete this question, its answers and responses?|, - lastUpdated => 1035951626 - }, - - '55' => { - message => q|View responses.|, - lastUpdated => 1037555778 - }, - - '27' => { - message => q|Add an opinion (agree/disagree) answer scale.|, - lastUpdated => 1035948010 - }, - - '84' => { - message => q|Max Responses Per User|, - lastUpdated => 1075639389 - }, - - '74' => { - message => q|Are you certain you wish to delete all the responses?|, - lastUpdated => 1037574455 - }, - - '57' => { - message => q|Comments|, - lastUpdated => 1037556124 - }, - - '61' => { - message => q|View grade book.|, - lastUpdated => 1037556642 - }, - - '20' => { - message => q|Is this answer correct?|, - lastUpdated => 1035436321 - }, - - 'question.add.url' => { - message => q|The URL to add a new question to the survey.|, - lastUpdated => 1149654653, - }, - - 'question.add.label' => { - message => q|The default label for question.add.url.|, - lastUpdated => 1149654653, - }, - - 'section.add.url' => { - message => q|The URL to add a new section to the survey.|, - lastUpdated => 1149654653, - }, - - 'section.add.label' => { - message => q|The default label for section.add.url.|, - lastUpdated => 1149654653, - }, - - 'user.canTakeSurvey' => { - message => q|A boolean indicating whether the current user has the rights to take the survey.|, - lastUpdated => 1149654653, - }, - - 'form.header' => { - message => q|The required form elements that go at the top of the survey questions.|, - lastUpdated => 1149654653, - }, - - 'form.footer' => { - message => q|The required form elements that go after the survey questions.|, - lastUpdated => 1149654653, - }, - - 'form.submit' => { - message => q|The default submit button for the survey response.|, - lastUpdated => 1149654653, - }, - - 'questions.sofar.label' => { - message => q|The default label for indicating how many questions have been answered to this point in the survey.|, - lastUpdated => 1149654653, - }, - - 'start.newresponse.label' => { - message => q|The default label for start.newresponse.url.|, - lastUpdated => 1149654653, - }, - - 'start.newresponse.url' => { - message => q|The URL to start a new response to the survey after the user has already taken the survey once.|, - lastUpdated => 1149654653, - }, - - 'thanks.survey.label' => { - message => q|A message thanking the user for completing the survey.|, - lastUpdated => 1149654653, - }, - - 'thanks.quiz.label' => { - message => q|A message thanking the user for completing the quiz.|, - lastUpdated => 1149654653, - }, - - 'questions.total' => { - message => q|The total number of questions in the survey.|, - lastUpdated => 1149654653, - }, - - 'questions.correct.count.label' => { - message => q|The default label for questions.correct.count.|, - lastUpdated => 1149654653, - }, - - 'questions.correct.percent.label' => { - message => q|The default label for questions.correct.percent.|, - lastUpdated => 1149654653, - }, - - 'mode.isSurvey' => { - message => q|A boolean indicating whether we are in survey mode or quiz mode.|, - lastUpdated => 1149654653, - }, - - 'survey.noprivs.label' => { - message => q|A message telling the user that they do not have the privileges necessary to take this survey.|, - lastUpdated => 1149654653, - }, - - 'quiz.noprivs.label' => { - message => q|A message telling the user that they do not have the privileges necessary to take the quiz.|, - lastUpdated => 1149654653, - }, - - 'response.id' => { - message => q|The unique id for the current response for this user.|, - lastUpdated => 1149654653, - }, - - 'response.count' => { - message => q|The number of responses this user has provided for this survey.|, - lastUpdated => 1149654653, - }, - - 'user.isFirstResponse' => { - message => q|A boolean indicating whether this is the first response for this user.|, - lastUpdated => 1149654653, - }, - - 'user.canRespondAgain' => { - message => q|A boolean indicating whether the user is allowed to respond to this survey again.|, - lastUpdated => 1149654653, - }, - - 'questions.sofar.count' => { - message => q|The number of questions that have been answered to this point in the survey.|, - lastUpdated => 1149654653, - }, - - 'questions.correct.count' => { - message => q|The number of questions the user has correct in the quiz to this point.|, - lastUpdated => 1149654653, - }, - - 'questions.correct.percent' => { - message => q|The percentage of questions that the user has correct in the quiz to this point.|, - lastUpdated => 1149654653, - }, - - 'response.isComplete' => { - message => q|A boolean indicating whether the user has answered all of the questions for this survey response.|, - lastUpdated => 1149654653, - }, - - 'question_loop' => { - message => q|A loop which contains the questions for this survey response.|, - lastUpdated => 1149654653, - }, - - 'question.question' => { - message => q|The survey question itself.|, - lastUpdated => 1149654653, - }, - - 'question.allowComment' => { - message => q|A boolean indicating whether this question allows comments or not.|, - lastUpdated => 1149654653, - }, - - 'question.id' => { - message => q|The unique id for this question.|, - lastUpdated => 1149654653, - }, - - 'question.comment.field' => { - message => q|The form field to enter comments for this question.|, - lastUpdated => 1149654653, - }, - - 'question.comment.label' => { - message => q|The default label for question.comment.field.|, - lastUpdated => 1149654653, - }, - - 'question.answer.field' => { - message => q|The form field containing the possible answers for this question.|, - lastUpdated => 1149654653, - }, - - 'section.questions_loop' => { - message => q|A loop containing all the questions in this section of the survey with edit controls.|, - lastUpdated => 1149654653, - }, - - 'section.edit_loop' => { - message => q|A loop containing all the sections and their questions with edit controls.|, - lastUpdated => 1162445117, - }, - - 'section.edit.controls' => { - message => q|A toolbar to use to edit, delete or move this section.|, - lastUpdated => 1162270258, - }, - - 'section.edit.sectionName' => { - message => q|The name of this section of questions.|, - lastUpdated => 1162270301, - }, - - 'question.edit.controls' => { - message => q|A toolbar to use to edit, delete or move this question.|, - lastUpdated => 1162270256, - }, - - 'question.edit.question' => { - message => q|The question to be edited.|, - lastUpdated => 1149654653, - }, - - 'question.edit.id' => { - message => q|The unique id for this question.|, - lastUpdated => 1149654653, - }, - - 'section.edit.id' => { - message => q|The unique id for this section.|, - lastUpdated => 1162270283, - }, - - '10' => { - message => q|Quiz|, - lastUpdated => 1033949566 - }, - - '31' => { - message => q|True|, - lastUpdated => 1037498842 - }, - - '35' => { - message => q|Somewhat Agree|, - lastUpdated => 1037498927 - }, - - '11' => { - message => q|Mode|, - lastUpdated => 1033949647 - }, - - 'user.canViewReports' => { - message => q|A boolean indicating whether the user has the privileges to view survey reports.|, - lastUpdated => 1149654717, - }, - - 'delete.all.responses.url' => { - message => q|This URL will delete all of the responses to this survey.|, - lastUpdated => 1149654717, - }, - - 'delete.all.responses.label' => { - message => q|The default label for delete.all.responses.url.|, - lastUpdated => 1149654717, - }, - - 'export.answers.url' => { - message => q|The URL to create a tab delimited file containing all of the answers to the questions in this survey.|, - lastUpdated => 1149654717, - }, - - 'export.answers.label' => { - message => q|The default label for export.answers.url.|, - lastUpdated => 1149654717, - }, - - 'export.questions.url' => { - message => q|The URL to create a tab delimited file containing all of the questions in this survey.|, - lastUpdated => 1149654717, - }, - - 'export.questions.label' => { - message => q|The default label for export.questions.url.|, - lastUpdated => 1149654717, - }, - - 'export.responses.url' => { - message => q|The URL to create a tab delimited file containing all of the responses to the questions in this survey.|, - lastUpdated => 1149654717, - }, - - 'export.responses.label' => { - message => q|The default label for export.responses.url|, - lastUpdated => 1149654717, - }, - - 'export.composite.url' => { - message => q|The URL to create a tab delimited file containing a composite view of all of the data in this survey.|, - lastUpdated => 1149654717, - }, - - 'export.composite.label' => { - message => q|The default label for export.composite.url.|, - lastUpdated => 1149654717, - }, - - 'report.gradebook.url' => { - message => q|The URL to view the gradebook report for this quiz.|, - lastUpdated => 1149654717, - }, - - 'report.gradebook.label' => { - message => q|The default label for report.gradebook.url.|, - lastUpdated => 1149654717, - }, - - 'report.overview.url' => { - message => q|The URL to view statistical overview report for this survey.|, - lastUpdated => 1149654717, - }, - - 'report.overview.label' => { - message => q|The default label for report.overview.url.|, - lastUpdated => 1149654717, - }, - - 'survey.url' => { - message => q|The URL to view the survey. Usually used to get back to the survey after looking at a report.|, - lastUpdated => 1149654717, - }, - - 'survey.label' => { - message => q|The default label for survey.url.|, - lastUpdated => 1149654717, - }, - - '78' => { - message => q|Total Time|, - lastUpdated => 1038782125 - }, - - '48' => { - message => q|You are not currently eligible to participate in this survey. |, - lastUpdated => 1037499301 - }, - - '87' => { - message => q|Click here to start a new response.|, - lastUpdated => 1075639972 - }, - - '77' => { - message => q|End Time|, - lastUpdated => 1038782119 - }, - - '29' => { - message => q|Add a text answer.|, - lastUpdated => 1035874640 - }, - - '65' => { - message => q|Export composite summary.|, - lastUpdated => 1037556821 - }, - - '50' => { - message => q|Next|, - lastUpdated => 1037499410 - }, - - '39' => { - message => q|Not Applicable|, - lastUpdated => 1037574804 - }, - - '64' => { - message => q|Export responses.|, - lastUpdated => 1037556721 - }, - - '12' => { - message => q|Who can take the survey?|, - lastUpdated => 1033949789 - }, - - '41' => { - message => q|Frequently|, - lastUpdated => 1037574786 - }, - - '58' => { - message => q|Statistical Overview|, - lastUpdated => 1037556179 - }, - - '15' => { - message => q|Allow comment?|, - lastUpdated => 1035429212 - }, - - '81' => { - message => q|Anonymous responses?|, - lastUpdated => 1059069492 - }, - - '52' => { - message => q|Score|, - lastUpdated => 1037506007 - }, - - '60' => { - message => q|Back to survey.|, - lastUpdated => 1037556626 - }, - - '56' => { - message => q|View comments.|, - lastUpdated => 1037555787 - }, - - '45' => { - message => q|Are you certain you wish to delete this answer and its responses?|, - lastUpdated => 1035951913 - }, - - '66' => { - message => q|Responses|, - lastUpdated => 1037557127 - }, - - '73' => { - message => q|Delete all the responses.|, - lastUpdated => 1037573893 - }, - - '86' => { - message => q|Progress|, - lastUpdated => 1075639914 - }, - - '19' => { - message => q|Answer|, - lastUpdated => 1035436296 - }, - - '76' => { - message => q|Start Time|, - lastUpdated => 1038782111 - }, - - '62' => { - message => q|Export answers.|, - lastUpdated => 1037556697 - }, - - '54' => { - message => q|Percentage|, - lastUpdated => 1037555267 - }, - - '67' => { - message => q|User|, - lastUpdated => 1037558860 - }, - - '70' => { - message => q|Individual Responses|, - lastUpdated => 1037573240 - }, - - '2' => { - message => q|Edit Survey|, - lastUpdated => 1033943825 - }, - - '17' => { - message => q|Survey Question, Add/Edit|, - lastUpdated => 1110068088, - }, - 'assetName' => { message => q|Survey|, - lastUpdated => 1128832543 - }, - - '88' => { - message => q|Survey Template|, - lastUpdated => 1078223096 - }, - - '30' => { - message => q|Add a new question.|, - lastUpdated => 1035944708 - }, - - '82' => { - message => q|Terminate Survey|, - lastUpdated => 1068901816 - }, - - '25' => { - message => q|Add a true/false answer.|, - lastUpdated => 1035947960 - }, - - '28' => { - message => q|Add a question.|, - lastUpdated => 1035872173 - }, - - '83' => { - message => q|Questions Per Page|, - lastUpdated => 1075639327 - }, - - '75' => { - message => q|Edit this question.|, - lastUpdated => 1038778819 - }, - - '40' => { - message => q|Always|, - lastUpdated => 1037574725 - }, - - '14' => { - message => q|Question|, - lastUpdated => 1035428770 - }, - - '69' => { - message => q|Delete this user's responses.|, - lastUpdated => 1037573082 - }, - - '59' => { - message => q|View statistical overview.|, - lastUpdated => 1037556614 - }, - - '49' => { - message => q|You may not take this quiz at this time.|, - lastUpdated => 1037499363 - }, - - '24' => { - message => q|Add a multiple choice answer.|, - lastUpdated => 1035874502 - }, - - '53' => { - message => q|Responses|, - lastUpdated => 1037555255 - }, - - '79' => { - message => q|minutes|, - lastUpdated => 1038789595 - }, - - '42' => { - message => q|Occasionally|, - lastUpdated => 1037574859 - }, - - '22' => { - message => q|Answer Type|, - lastUpdated => 1035864413 - }, - - '46' => { - message => q|Thank you for taking the time to complete our survey.|, - lastUpdated => 1037499049 - }, - - '13' => { - message => q|Who can view reports?|, - lastUpdated => 1033949863 - }, - - '23' => { - message => q|Add a new answer.|, - lastUpdated => 1035864494 - }, - - '6' => { - message => q|Random|, - lastUpdated => 1033944643 - }, - - '85' => { - message => q|Questions Per Response|, - lastUpdated => 1075639549 - }, - - '36' => { - message => q|Somewhat Disagree|, - lastUpdated => 1037498872 - }, - - '9' => { - message => q|Survey|, - lastUpdated => 1033949540 - }, - - '51' => { - message => q|Comments?|, - lastUpdated => 1037499470 - }, - - '47' => { - message => q|You have completed this quiz.|, - lastUpdated => 1037499131 - }, - - '8' => { - message => q|Question Order|, - lastUpdated => 1033949393 - }, - - '38' => { - message => q|Strongly Disagree|, - lastUpdated => 1037498903 - }, - - 'view template description' => { - message => q|This template is used to display the Survey itself.|, - lastUpdated => 1146455534, - }, - - 'response template description' => { - message => q|This template is used to display the questions and answers for the user to pick.|, - lastUpdated => 1146455536, - }, - - 'gradebook template description' => { - message => q|This template is used to display, on a user-by-user basis how many questions they got -correct and what percentage answered were correct.|, - lastUpdated => 1146455538, - }, - - 'overview template description' => { - message => q|This template is used to display a statistical overview of the all responses to the Survey.|, - lastUpdated => 1146455541, - }, - - '8 description' => { - message => q|The order the questions will be asked. Sequential displays the questions in the order you create them. Random displays the questions randomly. Response driven displays the questions in order based on the responses of the users.|, - lastUpdated => 1146455543, - }, - - '83 description' => { - message => q|The number of questions that will be displayed per page. The default is 1.|, - lastUpdated => 1146455544, - }, - - '11 description' => { - message => q|By default the Survey is in survey mode. This allows it to ask questions of your users. However, if you switch to Quiz mode, you can have a self-correcting test of your user's knowledge.|, - lastUpdated => 1146455546, - }, - - '81 description' => { - message => q|Select whether or not the survey will record and display information that can identify a user and their responses. If left at the default value of "No", the survey will record the user's IP address as well as their WebGUI User ID and Username if logged in. This info will then be available in the survey's reports. If set to "Yes", these three fields will contain scrambled data that can not be traced to a particular user.|, - lastUpdated => 1146455548, - }, - - '84 description' => { - message => q|The number of times the user can attempt to get the correct answer on each question. The default is 1.|, - lastUpdated => 1146455549, - }, - - '85 description' => { - message => q|The number of questions given to each user.|, - lastUpdated => 1168642765, - }, - - '12 description' => { - message => q|Which users can participate in the survey?|, - lastUpdated => 1146455552, - }, - - '13 description' => { - message => q|Who can view the results of the survey?|, - lastUpdated => 1146455553, - }, - - 'what next description' => { - message => q|After creating a new Survey, you may either start adding questions or go back to the page where -the survey was added.|, - lastUpdated => 1167193079, - }, - - - '34' => { - message => q|Agree|, - lastUpdated => 1037498914 - }, - - '37' => { - message => q|Disagree|, - lastUpdated => 1037498886 - }, - - '43' => { - message => q|Never|, - lastUpdated => 1037574752 - }, - - '5' => { - message => q|Sequential|, - lastUpdated => 1033944535 - }, - - 'cannot delete the last answer' => { - message=>q|You cannot delete the last answer from a question. Every question must have at least one answer.|, - lastUpdated=>1083944535, - context=>q|This message is displayed when a user is trying to delete the last answer from a survey question.| - }, - - '1087' => { - message => q|Gradebook Report Template|, - lastUpdated => 1078513217 - }, - - 'title' => { - message => q|The default title of the report.|, - lastUpdated => 1149654771, - }, - - 'question.count' => { - message => q|The number of questions in the survey.|, - lastUpdated => 1149654771, - }, - - 'response.user.label' => { - message => q|The default label for response.user.name.|, - lastUpdated => 1149654771, - }, - - 'response.count.label' => { - message => q|The default label for response.count.correct.|, - lastUpdated => 1149654771, - }, - - 'response.percent.label' => { - message => q|The default label for response.percent.|, - lastUpdated => 1149654771, - }, - - 'response_loop' => { - message => q|A loop containing a list of responses.|, - lastUpdated => 1149654771, - }, - - 'response.url' => { - message => q|The URL to view this response.|, - lastUpdated => 1149654771, - }, - - 'response.user.name' => { - message => q|The username of the user that gave this response.|, - lastUpdated => 1149654771, - }, - - 'response.count.correct' => { - message => q|The total number of questions that this user got correct.|, - lastUpdated => 1149654771, - }, - - 'response.percent' => { - message => q|The percentage of correct questions.|, - lastUpdated => 1149654771, - }, - - '1089' => { - message => q|Survey Response Template|, - lastUpdated => 1078515839 - }, - - 'delete.url' => { - message => q|The URL to delete this response.|, - lastUpdated => 1149654822, - }, - - 'delete.label' => { - message => q|The default label for delete.url.|, - lastUpdated => 1149654822, - }, - - 'start.date.label' => { - message => q|The default label for start.date.human.|, - lastUpdated => 1149654822, - }, - - 'start.date.epoch' => { - message => q|The epoch representation of when the user started the survey response.|, - lastUpdated => 1149654822, - }, - - 'start.date.human' => { - message => q|The human representation of the date when the user started the response.|, - lastUpdated => 1149654822, - }, - - 'start.time.human' => { - message => q|The human representation of the time when the user started the response.|, - lastUpdated => 1149654822, - }, - - 'end.date.label' => { - message => q|The default label for end.date.human.|, - lastUpdated => 1149654822, - }, - - 'end.date.epoch' => { - message => q|The epoch representation of the date when the user completed this response.|, - lastUpdated => 1149654822, - }, - - 'end.date.human' => { - message => q|The human representation of the date when the user completed this response.|, - lastUpdated => 1149654822, - }, - - 'end.time.human' => { - message => q|The human representation of the time when the user completed this response.|, - lastUpdated => 1149654822, - }, - - 'duration.label' => { - message => q|The default label for the duration.|, - lastUpdated => 1149654822, - }, - - 'duration.minutes' => { - message => q|The number of minutes it took to complete the survey.|, - lastUpdated => 1149654822, - }, - - 'duration.minutes.label' => { - message => q|A label for "minutes".|, - lastUpdated => 1149654822, - }, - - 'duration.seconds' => { - message => q|The left over seconds from the duration.minutes.|, - lastUpdated => 1167193028, - }, - - 'duration.seconds.label' => { - message => q|A label for "seconds".|, - lastUpdated => 1149654822, - }, - - 'answer.label' => { - message => q|The internationalized word "Answer". If the survey is not in quiz mode, this label will be blank.|, - lastUpdated => 1149654822, - }, - - 'response.label' => { - message => q|The internationalized word "Responses".|, - lastUpdated => 1149654822, - }, - - 'comment.label' => { - message => q|The internationalized word "Comments".|, - lastUpdated => 1149654822, - }, - - 'question' => { - message => q|The question itself.|, - lastUpdated => 1149654822, - }, - - 'question.isRadioList' => { - message => q|A boolean indicating whether this question's answers are a radio list.|, - lastUpdated => 1149654822, - }, - - 'question.response' => { - message => q|The user's response to this question.|, - lastUpdated => 1149654822, - }, - - 'question.comment' => { - message => q|The user's comment on this question (if any).|, - lastUpdated => 1149654822, - }, - - 'question.isCorrect' => { - message => q|A boolean indicating whether the user got this question correct.|, - lastUpdated => 1149654822, - }, - - 'question.answer' => { - message => q|The correct answer for this question.|, - lastUpdated => 1149654822, - }, - - '1091' => { - message => q|Statistical Overview Report Template|, - lastUpdated => 1078517114 - }, - - 'report answer.label' => { - message => q|The internationalized label, "Answers".|, - lastUpdated => 1149654954, - }, - - 'report response.count.label' => { - message => q|The default label for response.count.|, - lastUpdated => 1149654954, - }, - - 'show.responses.label' => { - message => q|The default label that will display responses.|, - lastUpdated => 1149654954, - }, - - 'show.comments.label' => { - message => q|The default label that will display comments.|, - lastUpdated => 1149654954, - }, - - 'report question_loop' => { - message => q|A loop containing questions.|, - lastUpdated => 1149654954, - }, - - 'question.response.total' => { - message => q|The total number of responses for this answer.|, - lastUpdated => 1149654954, - }, - - 'answer_loop' => { - message => q|A loop containing the answers and responses for this question.|, - lastUpdated => 1149654954, - }, - - 'answer.isCorrect' => { - message => q|A boolean indicating whether this answer is marked correct.|, - lastUpdated => 1149654954, - }, - - 'answer' => { - message => q|The answer itself.|, - lastUpdated => 1149654954, - }, - - 'answer.response.count' => { - message => q|The total number of responses given for this answer.|, - lastUpdated => 1149654954, - }, - - 'answer.response.percent' => { - message => q|The percent of responses to this question that went to this answer.|, - lastUpdated => 1149654954, - }, - - 'comment_loop' => { - message => q|A loop that contains all of the comments for this answer.|, - lastUpdated => 1149654954, - }, - - 'answer.comment' => { - message => q|A comment.|, - lastUpdated => 1149654954, - }, - - 'overview template' => { - message => q|Overview template|, - lastUpdated => 0, - context => q|Form label indicating the overview template.| - }, - - 'gradebook template' => { - message => q|Gradebook template|, - lastUpdated => 0, - context => q|Form label indicating the gradebook template.| - }, - - 'response template' => { - message => q|Response template|, - lastUpdated => 0, - context => q|Form label indicating the response template.| - }, - - 'view template' => { - message => q|View template|, - lastUpdated => 0, - context => q|Form label indicating the response template.| - }, - - '745' => { - message => q|Go back to the page.|, - lastUpdated => 1110006174, - }, - - '45' => { - message => q|No, I made a mistake.|, - lastUpdated => 1110006259, - }, - - '14 description' => { - message => q|This is the question that the user will be asked.|, - lastUpdated => 1146455568, - }, - - '15 description' => { - message => q|If set to Yes, then the user will be allowed to add a comment to their response to this question.|, - lastUpdated => 1146455578, - }, - - '16 description' => { - message => q|If set to Yes, then the answers will be shuffled for each user.|, - lastUpdated => 1146455581, - }, - - '21 description' => { - message => q|Used to define the question that follows this one when the question order for the survey -is set to "response".|, - lastUpdated => 1146455589, - }, - - 'what next question description' => { - message => q|

    After defining the question, you may supply an answer:

    -
      -
    • Multiple Choice
    • -
    • Text
    • -
    • Frequency
    • -
    • Opinion
    • -
    • Or you may return to the survey
    • -
    |, - lastUpdated => 1146804196, - }, - - '744' => { - message => q|What next?|, - lastUpdated => 1035864828 - }, - - '19 description' => { - message => q|The answer to this question.|, - lastUpdated => 1119993924, - }, - - '20 description' => { - message => q|If you have set the Survey to Quiz mode, then you can define if this answer -is correct or not.|, - lastUpdated => 1119993924, - }, - - 'what next answer description' => { - message => q|After defining the answer, you can add an answer to this question, addi - another question, edit the current question or go back to the page containing the - Survey.|, - lastUpdated => 1146455600, - }, - - 'survey asset template variables title' => { - message => q|Survey Asset Template Variables|, - lastUpdated => 1168644075 - }, - - 'templateId' => { - message => q|The ID of the template to show the Survey.|, - lastUpdated => 1168639537, - }, - - 'Survey_id' => { - message => q|The unique ID of this Survey. This is different from the Asset ID.|, - lastUpdated => 1168639537, - }, - - 'questionOrder' => { - message => q|Defines the order of the questions in the survey, "sequential", "random", "response" or "section".|, - context => q|The strings in quotes are literals. They should not be translated.|, - lastUpdated => 1168639812, - }, - - 'groupToTakeSurvey' => { - message => q|The ID of the group that is allowed to take the Survey.|, - lastUpdated => 1168639812, - }, - - 'groupToViewReports' => { - message => q|The ID of the group that is allowed to view reports from the Survey.|, - lastUpdated => 1168639812, - }, - - 'mode' => { - message => q|The mode the survey will run in, either "survey" or "quiz".|, - context => q|The strings in quotes are literals. They should not be translated.|, - lastUpdated => 1168639812, - }, - - 'anonymous' => { - message => q|A conditional variable showing whether or not this Survey as configured to be anonymous.|, - lastUpdated => 1168639812, - }, - - 'maxResponsesPerUser' => { - message => q|The number of times the user can attempt to get the correct answer on each question. The default is 1.|, - lastUpdated => 1168643566, - }, - - 'questionsPerPage' => { - message => q|The number of questions given to each user.|, - lastUpdated => 1168643573, - }, - - 'questionsPerPage' => { - message => q|The number of questions that will be displayed per page.|, - lastUpdated => 1168643669, - }, - - 'overviewTemplateId' => { - message => q|The ID of the template used to show the overview screen.|, - lastUpdated => 1168643669, - }, - - 'gradebookTemplateId' => { - message => q|The ID of the template used to show the gradebook screen.|, - lastUpdated => 1168643669, - }, - - 'responseTemplateId' => { - message => q|The ID of the template used to show the Survey Response screen.|, - lastUpdated => 1168643669, - }, - - 'defaultSectionId' => { - message => q|The ID of the default section.|, - lastUpdated => 1168643669, - }, - + lastUpdated => 1224686319 + }, + 'edit survey' => { + message => q|Edit Survey|, + lastUpdated => 1224686319 + }, + 'take survey' => { + message => q|Take Survey|, + lastUpdated => 1224686319 + }, + 'view reports' => { + message => q|View Results|, + lastUpdated => 1224686319 + }, + 'continue button' => { + message => q|Continue|, + lastUpdated => 1224686319 + }, + 'add section' => { + message => q|Add Section|, + lastUpdated => 1224686319 + }, + 'add question' => { + message => q|Add Question|, + lastUpdated => 1224686319 + }, + 'add answer' => { + message => q|Add Answer|, + lastUpdated => 1224686319 + }, + 'submit' => { + message => q|Submit|, + lastUpdated => 1224686319 + }, + 'copy' => { + message => q|Copy|, + lastUpdated => 1224686319 + }, + 'cancel' => { + message => q|Cancel|, + lastUpdated => 1224686319 + }, + 'delete' => { + message => q|Delete|, + lastUpdated => 1224686319 + }, + 'section number' => { + message => q|Section Number:|, + lastUpdated => 1224686319 + }, + 'questions on section page' => { + message => q|Questions on section page:|, + lastUpdated => 1224686319 + }, + 'section name' => { + message => q|Section name:|, + lastUpdated => 1224686319 + }, + 'randomize questions' => { + message => q|Randomize questions:|, + lastUpdated => 1224686319 + }, + 'section custom variable name' => { + message => q|Section custom variable name:|, + lastUpdated => 1224686319 + }, + 'section branch goto variable name' => { + message => q|Section branch goto variable name:|, + lastUpdated => 1224686319 + }, + 'questions per page' => { + message => q|Questions per page:|, + lastUpdated => 1224686319 + }, + 'section text' => { + message => q|Section text:|, + lastUpdated => 1224686319 + }, + 'title on every page' => { + message => q|Title on every page:|, + lastUpdated => 1224686319 + }, + 'text on every page' => { + message => q|Text on every page:|, + lastUpdated => 1224686319 + }, + 'terminal section' => { + message => q|Terminal section:|, + lastUpdated => 1224686319 + }, + 'terminal section url' => { + message => q|Terminal section URL:|, + lastUpdated => 1224686319 + }, + 'please enter section information' => { + message => q|Please enter section information|, + lastUpdated => 1224686319 + }, + 'please enter question information' => { + message => q|Please enter question information|, + lastUpdated => 1224686319 + }, + 'question number' => { + message => q|Question number:|, + lastUpdated => 1224686319 + }, + 'question text' => { + message => q|Question text:|, + lastUpdated => 1224686319 + }, + 'question variable name' => { + message => q|Question variable name.|, + lastUpdated => 1224686319 + }, + 'randomize answers' => { + message => q|Randomize answers:|, + lastUpdated => 1224686319 + }, + 'question type' => { + message => q|Question type:|, + lastUpdated => 1224686319 + }, + 'randomized words' => { + message => q|Randomized words:|, + lastUpdated => 1224686319 + }, + 'vertical display' => { + message => q|Vertical display:|, + lastUpdated => 1224686319 + }, + 'show text in button' => { + message => q|Show text in button:|, + lastUpdated => 1224686319 + }, + 'allow comment' => { + message => q|Allow comment:|, + lastUpdated => 1224686319 + }, + 'cols' => { + message => q|Cols:|, + lastUpdated => 1224686319 + }, + 'rows' => { + message => q|Rows:|, + lastUpdated => 1224686319 + }, + 'maximum number of answers' => { + message => q|Maximum number of answers:|, + lastUpdated => 1224686319 + }, + 'required' => { + message => q|Required|, + lastUpdated => 1224686319 + }, + 'question value' => { + message => q|Question value:|, + lastUpdated => 1224686319 + }, + 'please enter answer information' => { + message => q|Please enter answer information:|, + lastUpdated => 1224686319 + }, + 'answer number' => { + message => q|Answer number:|, + lastUpdated => 1224686319 + }, + 'answer text' => { + message => q|Answer text:|, + lastUpdated => 1224686319 + }, + 'recorded answer' => { + message => q|Recorded answer:|, + lastUpdated => 1224686319 + }, + 'jump to' => { + message => q|Jump to:|, + lastUpdated => 1224686319 + }, + 'text answer' => { + message => q|Text answer|, + lastUpdated => 1224686319 + }, + 'is this the correct answer' => { + message => q|Is this the correct answer|, + lastUpdated => 1224686319 + }, + 'yes' => { + message => q|Yes|, + lastUpdated => 1224686319 + }, + 'no' => { + message => q|No|, + lastUpdated => 1224686319 + }, + 'min' => { + message => q|Min|, + lastUpdated => 1224686319 + }, + 'max' => { + message => q|Max|, + lastUpdated => 1224686319 + }, + 'step' => { + message => q|Step|, + lastUpdated => 1224686319 + }, + 'verbatim' => { + message => q|Verbatim|, + lastUpdated => 1224686319 + }, + 'answer value' => { + message => q|Answer value:|, + lastUpdated => 1224686319 + }, + 'checked' => { + message => q|Checked|, + lastUpdated => 1224686319 + }, }; 1; diff --git a/www/extras/wobject/Survey/administersurvey.js b/www/extras/wobject/Survey/administersurvey.js new file mode 100644 index 000000000..737a3f980 --- /dev/null +++ b/www/extras/wobject/Survey/administersurvey.js @@ -0,0 +1,453 @@ +if (typeof Survey == "undefined") { + var Survey = {}; +} + +Survey.Form = new function() { + + var multipleChoice = {'Multiple Choice':1,'Gender':1,'Yes/No':1,'True/False':1,'Ideology':1, 'Race':1,'Party':1,'Education':1 + ,'Scale':1,'Agree/Disagree':1,'Oppose/Support':1,'Importance':1, + 'Likelihood':1,'Certainty':1,'Satisfaction':1,'Confidence':1,'Effectiveness':1,'Concern':1,'Risk':1,'Threat':1,'Security':1}; + var text = {'Text':1, 'Email':1, 'Phone Number':1, 'Text Date':1, 'Currency':1}; + var slider = {'Slider':1, 'Dual Slider - Range':1, 'Multi Slider - Allocate':1}; + var dateType = {'Date':1,'Date Range':1}; + var fileUpload = {'File Upload':1}; + var hidden = {'Hidden':1}; + + var hasFile; + var verb = 0; + var lastSection = 'first'; + + var toValidate; + + var sliderWidth = 500; + + var sliders; + +// this.submittimer; + + + this.displayQuestions = function(params){ + toValidate = new Array();//clear array + var qs = params.questions; + var s = params.section; + sliders = new Array(); + + //What to show and where + document.getElementById('survey').innerHTML = params.html; +//var te = document.createElement('span'); +//te.innerHTML = ""; +//document.getElementById('survey').appendChild(te); +//YAHOO.util.Event.addListener("testB", "click", function(){Survey.Comm.callServer('','loadQuestions');}); + + if(qs[0] != undefined){ + if(lastSection != s.id|| s.everyPageTitle > 0){ + document.getElementById('headertitle').style.display='block'; + } + if(lastSection != s.id|| s.everyPageText > 0){ + document.getElementById('headertext').style.display = 'block'; + } + + if(lastSection != s.id && s.questionsOnSectionPage != '1'){ + var span = document.createElement("div"); + span.innerHTML = ""; + span.style.display = 'block'; + + document.getElementById('header').appendChild(span); + YAHOO.util.Event.addListener("showQuestionsButton", "click", + function(){ + document.getElementById('showQuestionsButton').style.display = 'none'; + if(s.everyPageTitle == 0){ + document.getElementById('headertitle').style.display = 'none'; + } + if(s.everyPageText == 0){ + document.getElementById('headertext').style.display = 'none'; + } + document.getElementById('questions').style.display='inline'; + Survey.Form.addWidgets(qs); + }); + }else{ + document.getElementById('questions').style.display='inline'; + Survey.Form.addWidgets(qs); + } + lastSection = s.id; + }else{ + document.getElementById('headertitle').style.display='block'; + document.getElementById('headertext').style.display = 'block'; + document.getElementById('questions').style.display='inline'; + Survey.Form.addWidgets(qs); + } + } + + + + + //Display questions + this.addWidgets = function(qs){ + hasFile = false; + for(var i = 0; i < qs.length; i++){ + var q = qs[i]; + var verts = ''; + var verte = ''; + for(var x in q.answers){ + for(var y in q.answers[x]){ + if(q.answers[x][y] == undefined){q.answers[x][y] = '';} + } + } + + //Check if this question should be validated + if(q.required == 1){ + toValidate[q.id] = new Array(); + toValidate[q.id]['type'] = q.questionType; + toValidate[q.id]['answers'] = new Array(); + } + + + if(multipleChoice[q.questionType]){ + var butts = new Array(); + verb = 0; + for(var x = 0; x < q.answers.length; x++){ + var a = q.answers[x]; + if(toValidate[q.id]){ + toValidate[q.id]['answers'][a.id] = 1; + } + var b = document.getElementById(a.id+'button'); + /* + b = new YAHOO.widget.Button({ type: "checkbox", label: a.answerText, id: a.id+'button', name: a.id+'button', + value: a.id, + container: a.id+"container", checked: false }); + */ +// b.on("click", this.buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]); +// YAHOO.util.Event.addListener(a.id+'button', "click", this.buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]); + if(a.verbatim == 1){ + verb = 1; + } + YAHOO.util.Event.addListener(a.id+'button', "click", this.buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]); + b.hid = a.id; + butts.push(b); + } + } + else if(dateType[q.questionType]){ + for(var x = 0; x < q.answers.length; x++){ + var a = q.answers[x]; + if(toValidate[q.id]){ + toValidate[q.id]['answers'][a.id] = 1; + } + var calid = a.id+'container'; + var c = new YAHOO.widget.Calendar(calid,{title:'Choose a date:', close:true}); + c.selectEvent.subscribe(this.selectCalendar,[c,a.id],true); + c.render(); + c.hide(); + var b = new YAHOO.widget.Button({ label:"Select Date", id:"pushbutton"+a.id, container:a.id+'button' }); + b.on("click", this.showCalendar,[c]); + } + } + else if(slider[q.questionType]){ + //First run through and put up the span placeholders and find the max value for an answer, to know how big the allocation points will be. + var max = 0; + if(q.questionType == 'Dual Slider - Range'){ + new this.dualSliders(q); + }else{ + for(var s in q.answers){ + var a = q.answers[s]; + YAHOO.util.Event.addListener(a.id, "blur", this.sliderTextSet); + if(a.max - a.min > max){max = a.max - a.min;} + } + } + if(q.questionType == 'Multi Slider - Allocate'){ + //sliderManagers[sliderManagers.length] = new this.sliderManager(q,max); + for(var x = 0; x < q.answers.length; x++){ + var a = q.answers[x]; + if(toValidate[q.id]){ + toValidate[q.id]['total'] = a.max; + toValidate[q.id]['answers'][a.id] = 1; + } + } + new this.sliderManager(q,max); + } + else if(q.questionType == 'Slider'){ + new this.sliders(q); + } + } + + else if(fileUpload[q.questionType]){ + hasFile = true; + } + + else if(text[q.questionType]){ + var a = q.answers[x]; + if(toValidate[q.id]){ + toValidate[q.id]['answers'][a.id] = 1; + } + } + } + YAHOO.util.Event.addListener("submitbutton", "click", this.formsubmit); + } + + + this.formsubmit = function(event){ + var submit = 1;//boolean for if all was good or not + for(var i in toValidate){ + var answered = 0; + if(toValidate[i]['type'] == 'Multi Slider - Allocate'){ + var total = 0; + for(var z in toValidate[i]['answers']){ + total += Math.round(document.getElementById(z).value); + } + if(total == toValidate[i]['total']){answered = 1;} + else{ + var amountLeft = toValidate[i]['total']-total; + alert("Please allocate the remaining "+amountLeft+ "."); + } + }else{ + for(var z in toValidate[i]['answers']){ + var v = document.getElementById(z).value; + if(v != '' && v != undefined){ + answered = 1; + break; + } + } + } + if(answered == 0){ + submit = 0; + document.getElementById(i+'required').innerHTML = "*"; + }else{ + document.getElementById(i+'required').innerHTML = ""; + } + } + if(submit == 1){ +YAHOO.log("Submitting"); + Survey.Comm.callServer('','submitQuestions','surveyForm',hasFile); + } + } + + + + + this.dualSliders = function(q){ + var total = sliderWidth; +// var sliders = new Array(); + var a1 = q.answers[0]; + var a2 = q.answers[1]; + var scale = sliderWidth/a1.max; + + var id = q.id; + var a1id = a1.id; + var a2id = a2.id; + + var a1h = document.getElementById(a1id); + var a2h = document.getElementById(a2id); + var a1s = document.getElementById(a1id+'show'); + var a2s = document.getElementById(a2id+'show'); + var s = YAHOO.widget.Slider.getHorizDualSlider(id+'slider-bg', + a1id+"slider-min-thumb", a2id+"slider-max-thumb", + sliderWidth, 1*scale, [1,sliderWidth]); + sliders[id] = s; +//YAHOO.log(1); + + s.minRange = 4; + var updateUI = function () { + var min = Math.round(s.minVal/scale), + max = Math.round(s.maxVal/scale); + a1h.value = min; + a1s.innerHTML = min; + a2h.value = max; + a2s.innerHTML = max; + }; + + // Subscribe to the dual thumb slider's change and ready events to + // report the state. +// s.subscribe('ready', updateUI); + //s.subscribe('change', updateUI); + s.subscribe('slideEnd', updateUI); + } + this.sliders = function(q){ + var total = sliderWidth; + for(var i in q.answers){ + var a = q.answers[i]; + var step = Math.round(q.answers[i].step); + var min = Math.round(parseFloat(q.answers[i].min)); + var distance = Math.round(parseFloat(q.answers[i].max) + (-1 * min)); + var scale = Math.round(sliderWidth/distance); + var lang = YAHOO.lang; + var id = a.id; + var s = YAHOO.widget.Slider.getHorizSlider(id+'slider-bg', id+'slider-thumb', + 0, sliderWidth, (scale*step)); + s.scale = scale; + sliders[q.Survey_questionid] = new Array(); + sliders[q.Survey_questionid][id] = s; + s.input = a.id; + s.scale = scale; + document.getElementById(id).value = a.min; + var check = function() { + var t = document.getElementById(this.input); + t.value = this.getRealValue(); + }; + s.getRealValue = function() { + return Math.round(parseFloat(( (this.getValue() / total) * distance) + min )); + } + s.subscribe("slideEnd", check); + } + } + //an object which creates sliders for allocation type questions and then manages their events and keeps them from overallocating + this.sliderManager = function(q,t){ + var total = sliderWidth; + var step = Math.round(parseFloat(q.answers[0].step)); + var min = Math.round(parseFloat(q.answers[0].min)); + var distance = Math.round(parseFloat(q.answers[0].max) + (-1 * min)); + var scale = Math.round(sliderWidth/distance); + for(var i in q.answers){ + var a = q.answers[i]; + var Event = YAHOO.util.Event; + var lang = YAHOO.lang; + var id = a.id+'slider-bg'; + var s = YAHOO.widget.Slider.getHorizSlider(id, a.id+'slider-thumb', + 0, sliderWidth, scale*step); + s.animate = false; + if(sliders[q.id] == undefined){ + sliders[q.id] = new Array(); + } + sliders[q.id][a.id] = s; + s.input = a.id; + s.lastValue = 0; + var check = function() { + var t = 0; + for(var x in sliders[q.id]){ + t+= sliders[q.id][x].getValue(); + } + if(t > total){ + t -= this.getValue(); + t = Math.round(t); + this.setValue(total-t);// + (scale*step)); + document.getElementById(this.input).value = Math.round(parseFloat(( ((total-t) / total) * distance) + min )); + }else{ + this.lastValue = this.getValue(); + document.getElementById(this.input).value = this.getRealValue(); + } + }; + s.subscribe("change", check); + s.subscribe("slideEnd", check); + var manualEntry = function(e){ + // set the value when the 'return' key is detected + if (Event.getCharCode(e) === 13 || e.type == 'blur') { + var v = parseFloat(this.value, 10); + v = (lang.isNumber(v)) ? v : 0; +// v *= scale; + v = ( ( (v-min) / distance))*total; + // convert the real value into a pixel offset + for(var sl in sliders[q.id]){ + if(sliders[q.id][sl].input == this.id){ + sliders[q.id][sl].setValue(Math.round(v)); + } + } + } + } + Event.on(document.getElementById(s.input), "blur", manualEntry); + Event.on(document.getElementById(s.input), "keypress", manualEntry); + + s.getRealValue = function() { + return Math.round(parseFloat(( (this.getValue() / total) * distance) + min )); + } + document.getElementById(s.input).value = s.getRealValue(); + } + } + + this.selectCalendar = function(event,args,obj){ + var id = obj[1]; + var selected = args[0]; + var date = selected[0]; + var year = date[0], month = date[1], day = date[2]; + var input = document.getElementById(id); + input.value = month + "/" + day + "/" + year; + obj[0].hide(); + } + + + this.showCalendar = function(event,objs){ + objs[0].show(); + } + + this.sliderTextSet = function(event,objs){ + this.value = this.value * 1; + if(this.value == 'NaN'){this.value = 0;} + sliders[this.id].setValue(Math.round(this.value * sliders[this.id].scale)); + } + + this.buttonChanged = function(event,objs){ + var b = objs[0]; + var qid = objs[1]; + var maxA = objs[2]; + var butts = objs[3]; + var qsize = objs[4]; + var aid = objs[5]; + max = parseFloat(max); +// clearTimeout(Survey.Form.submittimer); + if(maxA == 1){ + if(b.className == 'mcbutton-selected'){ + document.getElementById(b.hid).value = 0; + b.className='mcbutton'; + }else{ + document.getElementById(b.hid).value = 1; + b.className='mcbutton-selected'; + } + for(var i in butts){ + if(butts[i] != b){ + butts[i].className='mcbutton'; + document.getElementById(butts[i].hid).value = ''; + } + } + } + else if(b.className == 'mcbutton'){ + var bscount = 0;//button selected count + for(var i in butts){ + if(butts[i].className == 'mcbutton-selected'){bscount++;} + } + var max = maxA - bscount;//= parseFloat(document.getElementById(qid+'max').innerHTML); + if(max == 0){ + b.className='mcbutton'; + //warn that options used up + } + else{ + b.className='mcbutton-selected'; + //document.getElementById(qid+'max').innerHTML = parseFloat(max-1); + document.getElementById(b.hid).value = 1; + } + }else{ + b.className='mcbutton'; + var bscount = 0;//button selected count + for(var i in butts){ + if(butts[i].className == 'mcbutton-selected'){bscount++;} + } + var max = maxA - bscount;//= parseFloat(document.getElementById(qid+'max').innerHTML); +// document.getElementById(qid+'max').innerHTML = parseFloat(max+1); + document.getElementById(b.hid).value = ''; + } +/* + if(qsize == 1 && b.className == 'mcbutton-selected'){ + if(! document.getElementById(aid+'verbatim')){ + Survey.Form.submittimer=setTimeout("Survey.Form.formsubmit()",500); + } + } +*/ + } +}(); + + + + +//---------------------------------------------------------------- +// +// Initialize survey +// +//---------------------------------------------------------------- +Survey.OnLoad = new function() { + var e = YAHOO.util.Event; + this.init = function() { + e.onDOMReady(this.initHandler); + } + this.initHandler = function(){ + Survey.Comm.setUrl('/'+document.getElementById('assetPath').value); + Survey.Comm.callServer('','loadQuestions'); + } +}(); + +Survey.OnLoad.init(); diff --git a/www/extras/wobject/Survey/administersurvey/comm.js b/www/extras/wobject/Survey/administersurvey/comm.js new file mode 100644 index 000000000..9947facb4 --- /dev/null +++ b/www/extras/wobject/Survey/administersurvey/comm.js @@ -0,0 +1,73 @@ +if (typeof Survey == "undefined") { + var Survey = {}; +} + +Survey.Comm= new function(){ + + + this.url = ''; + this.setUrl = function(u){this.url = u;} + var callMade = 0; + var request = function(sUrl,callback,postData,form, hasFile){ + if(form != undefined){ + if(hasFile){ + YAHOO.util.Connect.setForm(form,true); + //YAHOO.log('set file was true'); + }else{ + //YAHOO.log('set file was false'); + YAHOO.util.Connect.setForm(form); + } + //YAHOO.log('setForm was true'); + } + if(callMade == 1){ + alert("Waiting on previous request"); + }else{ + callMade = 1; +YAHOO.log(sUrl); + YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData); + } + } + + + this.callback = { + upload:function(o){ + callMade = 0; + Survey.Comm.callServer('','loadQuestions'); + }, + success:function(o){ + window.scrollTo(0,0); + callMade = 0; + var response = ''; + response = YAHOO.lang.JSON.parse(o.responseText); + if(response.type == 'displayquestions'){ + Survey.Form.displayQuestions(response); + }else if(response.type == 'forward'){ +//YAHOO.log("going to "+response.url); + location.href=response.url; + }else{ + alert("bad response"); + } + }, + failure: function(o){ + callMade = 0; + if(o.status == -1){ + alert("Last request timed out, please try again"); + }else{ + alert("Last request failed "+o.statusText); + } + }, + }; + + this.callServer = function(data,functionName,form,hasFile){ + var postData; + if(form == undefined){ + postData = "data="+YAHOO.lang.JSON.stringify(data,data); + //YAHOO.log(postData); + } + var sUrl = this.url + "?func="+functionName; + request(sUrl,this.callback,postData,form,hasFile); + } + + + +}(); diff --git a/www/extras/wobject/Survey/bg-fader-500.gif b/www/extras/wobject/Survey/bg-fader-500.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8072b855e8823c837de667cfd57c52b7705364d GIT binary patch literal 1197 zcmV;e1XBA)Nk%w1VFv<50OJS%>+9?F_4VQ5;mOI#r>CchiHWzjx7XL#|NsC0|NsC0 z|NsC0|NsC0|NsC0|NsC0A^8LW000O8EC2ui00#m^000F35Xniay*TU5yZ>M)j$~<` zXsWJk>%MR-&vb3yc&_h!@BhG{a7Zi~kI1BQ$!t2G(5Q4uty-_xtai)odcWYXcucki z&OdZIux9(t?wN)g#l|_r$;ddsAkM$c z&C)i|$F*Vdhz5UPjnY)LN zpo@Is47LzB5MZ=_u@oZYSMOTHip3me#5heN!x;V_K`LZ1kw(de9QB2Kv6AJ;6(=pk z6bVtA#$`3(rBr#7!_0y??e*ljliW)cEe{?|@pD2`r9my)bVpTZRa`?gJYBeyY1b25 zNhTE=6`4w#25^Ir;Wm~r6S(9%`Y>n%+uFAaN0E?JQ_u|!uhC={Y{DX00 z0FNR2SS-1RFbd537rpmn5HU7B_49IIi!#&H@%ZPT-9=eBX% zHRs=`ch`umJ93%h$dfBy&b+zv=g_AVm`=UA_3PNPYv0bjyZ7(l!;2qJzP$PK=+moT z&%V9;_wWl4m_H)E{rmXy>)+46zyJRL2L4Fhd<4`d;DHDxsNjMOHt67k^3fMiD->2} z;e{AxsNsejcIe@UAciR7h$NP1;)y7xsN#w&w&>!E7YZPNE-=<;-+s_3GOHtOi3kVY!$ zq?Dd%=m3aTs_CYjcIxS;poS`Hp@)i)i6elBLWd_bfO3PYpTOEGtFx*a!l|KfvIng) z;QA`By#fn^ub2ostg$W-n*m=a{tzZtRz}^0Qd(F^E0RZosg?6=^iD^<1c{&lWP-Cn?~Tj54)FHZY%MQ;c4&fBj{37gQc z!w38HuwD~`6R@`hbG5KM6~}w=KoM{7FT@|K(=oRhvxRNSg|&OHyZ#JJPrl;D8?sh6 z|CJ>Z)ya-+#jlIFxsjO!n1&3;r^@ ziJK)tZ?chQ9A?7NK->*pmk*b@<&|?jxni5o5W47{%K*78ZnTI_9mr9=i*# zM`!!(xaY3>?!5Qz`|rR9FZ}St7jOLW$S1G-^2|5y{PWO9Fa7k?S8x6G*k`Z(_S|>x L{rBLX5CH%?;B%7l literal 0 HcmV?d00001 diff --git a/www/extras/wobject/Survey/bg-fader.gif b/www/extras/wobject/Survey/bg-fader.gif new file mode 100644 index 0000000000000000000000000000000000000000..7db8eb72ce5849c507d61c2bc0dd4f02f51f8178 GIT binary patch literal 433 zcmV;i0Z#r$Nk%w1VbK5_0J8`H>+9?F_4VQ5;mOI#r>CchiHWzjx7XL#|Ns9000000 z00000000000000000000A^8LW000O8EC2ui0MP&(000F45Xniay*TU5yZ>M)j$~<` zXsWJk>%MR-&%s!WcbJ3w*L%NCkTcvAHN(S5DPo44Am~Txp?0hs>_)4>ax-5{_%gPX zD`!f2vX-dFX%FDt8WCzgE z($mz{*4NnC+S}aS-rwNi*#c(b=I7|?>g(*=M3r#X%8geqYc2CJSxX%)4VR9919 bafuyEwyfE+Xw#})%eJlCw{YW@hyVaP!M@qB literal 0 HcmV?d00001 diff --git a/www/extras/wobject/Survey/dd.js b/www/extras/wobject/Survey/dd.js new file mode 100644 index 000000000..86559ebba --- /dev/null +++ b/www/extras/wobject/Survey/dd.js @@ -0,0 +1,125 @@ +if (typeof Survey == "undefined") { + var Survey = {}; +} +var Dom = YAHOO.util.Dom; +var Event = YAHOO.util.Event; +var DDM = YAHOO.util.DragDropMgr; + +Survey.DDList = function(id, sGroup, config) { + + Survey.DDList.superclass.constructor.call(this, id, sGroup, config); + + this.logger = this.logger || YAHOO; + var el = this.getDragEl(); + Dom.setStyle(el, "opacity", 0.67); // The proxy is slightly transparent + + this.goingUp = false; + this.lastY = 0; +}; + +YAHOO.extend(Survey.DDList, YAHOO.util.DDProxy, { + + startDrag: function(x, y) { + this.logger.log(this.id + " startDrag"); + + // make the proxy look like the source element + var dragEl = this.getDragEl(); + var clickEl = this.getEl(); + Dom.setStyle(clickEl, "visibility", "hidden"); + + dragEl.innerHTML = clickEl.innerHTML; + + Dom.setStyle(dragEl, "color", Dom.getStyle(clickEl, "color")); + Dom.setStyle(dragEl, "backgroundColor", Dom.getStyle(clickEl, "backgroundColor")); + Dom.setStyle(dragEl, "border", "2px solid gray"); + }, + + endDrag: function(e) { + + var srcEl = this.getEl(); + var proxy = this.getDragEl(); + + // Show the proxy element and animate it to the src element's location + Dom.setStyle(proxy, "visibility", ""); + var a = new YAHOO.util.Motion( + proxy, { + points: { + to: Dom.getXY(srcEl) + } + }, + 0.2, + YAHOO.util.Easing.easeOut + ) + var proxyid = proxy.id; + var thisid = this.id; + + // Hide the proxy and show the source element when finished with the animation + a.onComplete.subscribe(function() { + Dom.setStyle(proxyid, "visibility", "hidden"); + Dom.setStyle(thisid, "visibility", ""); + }); + a.animate(); + }, + + onDragDrop: function(e, id) { + + // If there is one drop interaction, the li was dropped either on the list, + // or it was dropped on the current location of the source element. + if (DDM.interactionInfo.drop.length === 1) { + + // The position of the cursor at the time of the drop (YAHOO.util.Point) + var pt = DDM.interactionInfo.point; + + // The region occupied by the source element at the time of the drop + var region = DDM.interactionInfo.sourceRegion; + + // Check to see if we are over the source element's location. We will + // append to the bottom of the list once we are sure it was a drop in + // the negative space (the area of the list without any list items) + if (!region.intersect(pt)) { + var destEl = Dom.get(id); + var destDD = DDM.getDDById(id); + destEl.appendChild(this.getEl()); + destDD.isEmpty = false; + DDM.refreshCache(); + } + + } + Survey.Data.dragDrop(this.getEl()); + }, + + onDrag: function(e) { + + // Keep track of the direction of the drag for use during onDragOver + var y = Event.getPageY(e); + + if (y < this.lastY) { + this.goingUp = true; + } else if (y > this.lastY) { + this.goingUp = false; + } + + this.lastY = y; + }, + + onDragOver: function(e, id) { + + var srcEl = this.getEl(); + var destEl = Dom.get(id); + + // We are only concerned with list items, we ignore the dragover + // notifications for the list. + if (destEl.nodeName.toLowerCase() == "li") { + var orig_p = srcEl.parentNode; + var p = destEl.parentNode; + + if (this.goingUp) { + p.insertBefore(srcEl, destEl); // insert above + } else { + p.insertBefore(srcEl, destEl.nextSibling); // insert below + } + + DDM.refreshCache(); + } + } +}); diff --git a/www/extras/wobject/Survey/editsurvey.js b/www/extras/wobject/Survey/editsurvey.js new file mode 100644 index 000000000..5989a5376 --- /dev/null +++ b/www/extras/wobject/Survey/editsurvey.js @@ -0,0 +1,123 @@ +if (typeof Survey == "undefined") { + var Survey = {}; +} + +Survey.Data = new function(){ + var lastDataSet = {}; + var focus; + + + this.dragDrop = function(did){ + var type; +YAHOO.log('In drag drop'); + if(did.className.match("section")){type = 'section';} + else if(did.className.match("question")){type = 'question';} + else{ type = 'answer';} + + var first = {id:did.id,type:type}; + var before = document.getElementById(did.id).previousSibling; + + while(1){ + if( before == undefined || (before.id != undefined && before.id != '') ){ + break; + } + var before = before.previousSibling; + } + + var data = {id:'',type:''}; + + if(before != undefined && before.id != undefined && before.id != ''){ + if(before.className.match("section")){type = 'section';} + else if(before.className.match("question")){type = 'question';} + else{ type = 'answer';} + data = {id:before.id,type:type}; + } +YAHOO.log(first.id+' '+data.id); + Survey.Comm.dragDrop(first,data); + } + + + + this.clicked = function(){ + Survey.Comm.loadSurvey(this.id); + } + + + + this.loadData = function(d){ + focus = d.address;//What is the current highlighted item. + document.getElementById('sections').innerHTML=d.ddhtml; + + //add event handlers for if a tag is clicked + for(var x in d.ids){ +YAHOO.log('adding handler for '+ d.ids[x]); + YAHOO.util.Event.addListener(d.ids[x], "click", this.clicked); + new Survey.DDList(d.ids[x],"sections"); + } + + //add the add object buttons +// if(d.buttons['section']){ + document.getElementById('addSection').innerHTML = ''; + document.getElementById('addQuestion').innerHTML = ''; + document.getElementById('addAnswer').innerHTML = ''; + var button = new YAHOO.widget.Button({ label:"Add Section", id:"addsection", container:"addSection" }); + button.on("click", this.addSection); +// } +// if(d.buttons['question']){ + var button = new YAHOO.widget.Button({ label:"Add Question", id:"addquestion", container:"addQuestion" }); + button.on("click", this.addQuestion,d.buttons['question']); +// } + if(d.buttons['answer']){ + var button = new YAHOO.widget.Button({ label:"Add Answer", id:"addanswer", container:"addAnswer" }); + button.on("click", this.addAnswer,d.buttons['answer']); + } + + this.loadObjectEdit(d.edithtml,d.type); + lastDataSet = d; + } + + this.addSection = function(){ + Survey.Comm.newSection(); + } + + + this.addQuestion = function(e,id){ + Survey.Comm.newQuestion(id); + } + + this.addAnswer = function(e,id){ + Survey.Comm.newAnswer(id); + } + + this.loadObjectEdit = function(edit,type){ + if(edit){ + Survey.ObjectTemplate.loadObject(edit,type); + } + } + + + this.loadLast = function(){ + this.loadData(lastDataSet); + } +}(); + + +//---------------------------------------------------------------- +// +// Initialize survey +// +//---------------------------------------------------------------- +Survey.OnLoad = function() { + var e = YAHOO.util.Event; + return { + init: function() { + e.onDOMReady(this.initHandler); + }, + initHandler: function(){ + new YAHOO.util.DDTarget("sections","sections"); + Survey.Comm.loadSurvey(); + }, + } +}(); + +Survey.OnLoad.init(); diff --git a/www/extras/wobject/Survey/editsurvey/answer.js b/www/extras/wobject/Survey/editsurvey/answer.js new file mode 100644 index 000000000..f9fdabac7 --- /dev/null +++ b/www/extras/wobject/Survey/editsurvey/answer.js @@ -0,0 +1,69 @@ +if (typeof Survey == "undefined") { + var Survey = {}; +} + +Survey.AnswerTemplate = new function(){ + this.params; + this.loadAnswer = function(params){ + for(var p in params){ + if(params[p] == undefined){params[p] = '';} + } + + var html = "\ +
    \ +
    Please enter answer information
    \ +
    \ +\ +
    \ +\ +

    Answer Number: "+params.sequenceNumber + "\ +\ + \ + \ + "; + html = html + "

    Answer Text:\n\n"; + html = html + "

    Recorded Answer\n\n"; + html = html + "

    Jump to:"; + html = html + "

    Text Answer Cols: Rows: \ +

    "; + html = html + "

    Is this the correct answer:\n" + + this.makeRadio('isCorrect',[{text:'Yes',value:1},{text:'No',value:0}],params.isCorrect); + html = html + "

    Min:"; + html = html + "

    Max:"; + html = html + "

    Step:"; + html = html + "

    Verbatim:\n" + + this.makeRadio('verbatim',[{text:'Yes',value:1},{text:'No',value:0}],params.verbatim); + document.getElementById('edit').innerHTML = html; + + var butts = [{ text:"Submit", handler:function(){this.submit();}, isDefault:true },{ text:"Cancel", handler:function(){this.cancel();}} ]; + if(params.Survey_answerId != ''){ + butts[2] = { text:"Delete", handler:function(){Survey.Comm.deleteAnswer(Survey.AnswerTemplate.params.Survey_answerId);}}; + } + + var form = new YAHOO.widget.Dialog("answer", + { width : "500px", + fixedcenter : true, + visible : false, + constraintoviewport : true, + buttons : butts + }); + + form.callback = Survey.Comm.callback; + form.render(); + form.show(); + this.params = params; + }; + + this.makeRadio = function(name,values,checked){ + var html = ''; + for(var i in values){ + if(checked == values[i]['value']){ + html = html+ "" + values[i]['text']; + }else{ + html = html+ "" + values[i]['text']; + } + } + html = html + "\n"; + return html; + } +}(); diff --git a/www/extras/wobject/Survey/editsurvey/comm.js b/www/extras/wobject/Survey/editsurvey/comm.js new file mode 100644 index 000000000..a4c4b760d --- /dev/null +++ b/www/extras/wobject/Survey/editsurvey/comm.js @@ -0,0 +1,75 @@ +if (typeof Survey == "undefined") { + var Survey = {}; +} + +Survey.Comm = new function(){ + var callMade = 0; + + var request = function(sUrl,callback,postData){ + if(callMade == 1){ + alert("Waiting on previous request"); + }else{ + callMade = 1; + YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData); + } + } + this.callback = { + success:function(o){ + callMade = 0; + Survey.Data.loadData(YAHOO.lang.JSON.parse(o.responseText)); + }, + failure: function(o){ + callMade = 0; + alert("Last request failed"); + Survey.Data.loadLast(); + }, + timeout: 5000 + }; + this.loadSurvey = function(p){ + var postData = "data="+p; + var sUrl = "?func=loadSurvey"; + request(sUrl,this.callback,postData); + } + this.dragDrop = function(target,before){ + var p = {}; + p['target'] = target; + p['before'] = before; + var postData = "data="+YAHOO.lang.JSON.stringify(p); + var sUrl = "?func=dragDrop"; + request(sUrl,this.callback,postData); + } + this.submitEdit = function(p){ + var postData = "data="+YAHOO.lang.JSON.stringify(p); + var sUrl = "?func=submitEdit"; + request(sUrl,this.callback,postData); + } + this.newSection = function(){ + var sUrl = "?func=newObject"; + request(sUrl,this.callback); + } + this.newQuestion = function(id){ + var postData = "data="+id; + var sUrl = "?func=newObject"; + request(sUrl,this.callback,postData); + } + this.newAnswer = function(id){ + var postData = "data="+id; + var sUrl = "?func=newObject"; + request(sUrl,this.callback,postData); + } + this.deleteAnswer = function(id){ + var postData = "data="+id; + var sUrl = "?func=deleteAnswer"; + request(sUrl,this.callback,postData); + } + this.deleteQuestion = function(id){ + var postData = "data="+id; + var sUrl = "?func=deleteQuestion"; + request(sUrl,this.callback,postData); + } + this.deleteSection = function(id){ + var postData = "data="+id; + var sUrl = "?func=deleteSection"; + request(sUrl,this.callback,postData); + } +}(); diff --git a/www/extras/wobject/Survey/editsurvey/object.js b/www/extras/wobject/Survey/editsurvey/object.js new file mode 100644 index 000000000..cf67d07d1 --- /dev/null +++ b/www/extras/wobject/Survey/editsurvey/object.js @@ -0,0 +1,32 @@ +if (typeof Survey == "undefined") { + var Survey = {}; +} + +Survey.ObjectTemplate = new function(){ + + this.loadObject = function(html,type){ + + document.getElementById('edit').innerHTML = html; + + var butts = [ + { text:"Submit", handler:function(){this.submit();}, isDefault:true }, + { text:"Copy", handler:function(){document.getElementById('copy').value = 1; this.submit();}}, + { text:"Cancel", handler:function(){this.cancel();}}, + { text:"Delete", handler:function(){document.getElementById('delete').value = 1; this.submit();}} + ]; + + var form = new YAHOO.widget.Dialog(type, + { + width : "500px", + fixedcenter : true, + visible : false, + constraintoviewport : true, + buttons : butts + } ); + + form.callback = Survey.Comm.callback; + form.render(); + form.show(); + } +}(); + diff --git a/www/extras/wobject/Survey/editsurvey/question.html b/www/extras/wobject/Survey/editsurvey/question.html new file mode 100644 index 000000000..e63ace0ea --- /dev/null +++ b/www/extras/wobject/Survey/editsurvey/question.html @@ -0,0 +1,40 @@ +

    +
    Please enter question information
    +
    + +

    Question Number: + +

    Question Text:\n"; + \n"; +

    Question variable name:

    "; +

    Randomize answers:"; + checked>Yes + checked>No +

    Question type: + +

    Randomized words: + +

    Vertical display: + checked>Yes + checked>No + +

    Show text in button: + checked>Yes + checked>No + +

    Allow comment: + checked>Yes + checked>No +

       Cols: Rows: +

    +

    Maximum number of answers: +

    Required: + checked>Yes + checked>No +

    +
    +
    diff --git a/www/extras/wobject/Survey/editsurvey/question.js b/www/extras/wobject/Survey/editsurvey/question.js new file mode 100644 index 000000000..214c4b28b --- /dev/null +++ b/www/extras/wobject/Survey/editsurvey/question.js @@ -0,0 +1,112 @@ +if (typeof Survey == "undefined") { + var Survey = {}; +} + +Survey.QuestionTemplate = new function(){ + + this.loadQuestion = function(params){ + + for(var p in params){ + if(params[p] == undefined){params[p] = '';} + } + + var html = "\ +
    \ +
    Please enter question information
    \ +
    \ +\ +
    \ +

    Question Number: "+params.sequenceNumber + "\ +\ + \ + \ +

    Question Text:\n"; + if(params.questionText == ''){ + html = html + "\n"; + } + else{ + html = html + "\n"; + } + html = html + "

    Question variable name:

    "; + html = html + "

    Randomize answers:"; + + html = html+ this.makeRadio('randomizeAnswers',[{text:'Yes',value:1},{text:'No',value:0}],params.randomizeAnswers); + html = html + "

    Question type:"; + var questions = ['Agree/Disagree','Certainty','Concern','Confidence','Currency','Date','Date Range','Dual Slider - Range','Education','Effectiveness', + 'Email','File Upload','Gender','Hidden','Ideology','Importance','Likelihood','Multi Slider - Allocate','Multiple Choice','Oppose/Support', + 'Party','Phone Number','Race','Risk','Satisfaction','Scale','Security','Slider','Text','Text Date','Threat','True/False','Yes/No']; +// var questions = ['Multiple Choice','Gender','Yes/No','True/False','Agree/Disagree','Oppose/Support','Importance','Likelihood','Certainty','Satisfaction', +// 'Confidence','Effectiveness','Concern','Risk','Threat','Security','Ideology','Race','Party','Education', +// 'Text', 'Email', 'Phone Number', 'Text Date', 'Currency', +// 'Slider','Dual Slider - Range','Multi Slider - Allocate', 'Date','Date Range', 'File Upload','Hidden']; + + html = html + this.makeMenu('questionType',questions,questions,params.questionType); + + html = html + "\ +

    Randomized words:\ + \ +

    Vertical display:"; + + html = html+ this.makeRadio('verticalDisplay',[{text:'Yes',value:1},{text:'No',value:0}],params.verticalDisplay); + html = html + "

    Show text in button:"; + html = html + this.makeRadio('textInButton',[{text:'Yes',value:1},{text:'No',value:0}],params.textInButton); + html = html + "

    Allow comment:"; + html = html + this.makeRadio('allowComment',[{text:'Yes',value:1},{text:'No',value:0}],params.allowComment); + html = html + "

       Cols: Rows: \ +

    "; + html = html + "

    Maximum number of answers:"; + html = html + "

    Required:"; + html = html+ this.makeRadio('required',[{text:'Yes',value:1},{text:'No',value:0}],params.required); + html = html + "\ +

    \ +
    \ +
    \ + "; + + document.getElementById('edit').innerHTML = html; + + + var butts = [ { text:"Submit", handler:function(){this.submit();}, isDefault:true }, { text:"Cancel", handler:function(){this.cancel();}} ]; + if(params.Survey_questionId != ''){ + butts[2] = {text:"Delete", handler:function(){Survey.Comm.deleteQuestion(params.Survey_questionId);}}; + } + + var form = new YAHOO.widget.Dialog("question", + { width : "500px", + fixedcenter : true, + visible : false, + constraintoviewport : true, + buttons : butts + } ); + + form.callback = Survey.Comm.callback; + form.render(); + form.show(); + + } + this.makeMenu = function(name,values,text,selected){ + var html = "\n"; + return html; + } + this.makeRadio = function(name,values,checked){ + var html = ''; + for(var i in values){ + if(checked == values[i]['value']){ + html = html+ "" + values[i]['text']; + }else{ + html = html+ "" + values[i]['text']; + } + } + html = html + "\n"; + return html; + } + +}(); diff --git a/www/extras/wobject/Survey/editsurvey/section.js b/www/extras/wobject/Survey/editsurvey/section.js new file mode 100644 index 000000000..91d21a00a --- /dev/null +++ b/www/extras/wobject/Survey/editsurvey/section.js @@ -0,0 +1,28 @@ +if (typeof Survey == "undefined") { + var Survey = {}; +} + +Survey.SectionTemplate = new function(){ + + this.loadSection = function(html){ + + document.getElementById('edit').innerHTML = html; + + var butts = [ { text:"Submit", handler:function(){this.submit();}, isDefault:true }, { text:"Cancel", handler:function(){this.cancel();}}, + {text:"Delete", handler:function(){document.getElementById('delete').setValue(1); this.submit();}} + ]; + + var form = new YAHOO.widget.Dialog("section", + { width : "500px", + fixedcenter : true, + visible : false, + constraintoviewport : true, + buttons : butts + } ); + + form.callback = Survey.Comm.callback; + form.render(); + form.show(); + } +}(); + diff --git a/www/extras/wobject/Survey/gradient-glossy.png b/www/extras/wobject/Survey/gradient-glossy.png new file mode 100755 index 0000000000000000000000000000000000000000..cefdab036774b398b3c351f68c863874f242af50 GIT binary patch literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{G!3HF)&rH7sq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~-c6{&f;IEGZ*O8W8t|9>|%Hnui^fcHPGR|NrmUxo7*1-RCb{TD^9|$x~+zA31jJ{Dq&teyv=+ z?&z@-4<0@|d+x%62M-@TezI!K`o&9^uUNHa$IjjF-o3wc`O3B(yLRv0fAiMu=PzCy zJAU%*+jrNl-#Bpa@ZG!j9zA+|@zUiTyY`$sb$aXeofj@%x^eT?moHz>oISUB>-KFs zcCTK$e&gn?GiJ?MzH-f*H*b%hIJI`&hMzxwo;iDd`_A2)w`@Co=G@~aPrrZv@$TKb zt=o6)*}H$u+6_N`{M@#E*WbT?zkd7nU{Yi1 z?rG}tX7rvo*_xS?aULf#b33b;q381D7Oa}Bww5+4HcAVKH}i9u+wI!DTaQbmiJQ;m z$kAgiEDBAEX5PS<^yXD*GM0A$2EKzjOOvvfJuo8e**Kas zXLi#j4;d#0W-gIS2OAVbMf)^jPJHO-6K_&c&~Vzg=%|vg7)O($Q|Ix1g{c=T6jr#f dsAvSQayis=P(jr(>C_xamBUMBH!?6-0|0CW2iyPv literal 0 HcmV?d00001