diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 5315e458f..219a1723e 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -6,6 +6,9 @@ - The Syndicated Content asset was rewritten, and now uses 35% less memory and is 400% faster. - fixed #9025: Testing function of UsersOnline macro fails. + - Brand new Survey system. Make sure to export your old results as they will + not be imported, only the surveys themselves. + 7.6.2 - fixed: not allowed to add calendar events if in can edit group but not can add event group diff --git a/docs/gotcha.txt b/docs/gotcha.txt index e7a61db9e..1a86e9719 100644 --- a/docs/gotcha.txt +++ b/docs/gotcha.txt @@ -19,6 +19,10 @@ save you many hours of grief. * You must upgrade to 7.6.2 before you can upgrade to 7.6.3. + * 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.1 -------------------------------------------------------------------- diff --git a/docs/upgrades/packages-7.6.3/root_import_survey.wgpkg b/docs/upgrades/packages-7.6.3/root_import_survey.wgpkg new file mode 100644 index 000000000..37c8c7682 Binary files /dev/null and b/docs/upgrades/packages-7.6.3/root_import_survey.wgpkg differ diff --git a/docs/upgrades/upgrade_7.6.2-7.6.3.pl b/docs/upgrades/upgrade_7.6.2-7.6.3.pl index e0440748c..67aed5886 100644 --- a/docs/upgrades/upgrade_7.6.2-7.6.3.pl +++ b/docs/upgrades/upgrade_7.6.2-7.6.3.pl @@ -32,9 +32,199 @@ my $session = start(); # this line required createLastUpdatedField($session); createFieldShowOnline($session); upgradeSyndicatedContentTemplates($session); +migrateSurvey($session); finish($session); # this line required + + +#---------------------------------------------------------------------------- +# 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; + "); +} + + + #---------------------------------------------------------------------------- sub createLastUpdatedField { my $session = shift; diff --git a/lib/WebGUI/Asset/Wobject/Survey.pm b/lib/WebGUI/Asset/Wobject/Survey.pm deleted file mode 100644 index f9f64f7be..000000000 --- a/lib/WebGUI/Asset/Wobject/Survey.pm +++ /dev/null @@ -1,1450 +0,0 @@ -package WebGUI::Asset::Wobject::Survey; - -#------------------------------------------------------------------- -# WebGUI is Copyright 2001-2008 Plain Black Corporation. -#------------------------------------------------------------------- -# Please read the legal notices (docs/legal.txt) and the license -# (docs/license.txt) that came with this distribution before using -# this software. -#------------------------------------------------------------------- -# http://www.plainblack.com info@plainblack.com -#------------------------------------------------------------------- - -use strict; -use List::Util; -use Tie::CPHash; -use WebGUI::HTMLForm; -use WebGUI::International; -use WebGUI::SQL; -use WebGUI::Utility; -use WebGUI::Asset::Wobject; -use Digest::MD5 qw(md5_hex); - -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); -} - -#------------------------------------------------------------------- -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' - }, - } - }); - return $class->SUPER::definition($session, $definition); -} - -#------------------------------------------------------------------- -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; -} - -#------------------------------------------------------------------- -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; - - 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' - ); - - $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'), - ); - } - - return $tabform; -} - -#------------------------------------------------------------------- -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; -} - -#------------------------------------------------------------------- -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; -} - -#------------------------------------------------------------------- -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; -} - - - -#------------------------------------------------------------------- -sub getResponseId { - my $self = shift; - return $self->session->scratch->get($self->getResponseIdString); -} - -#------------------------------------------------------------------- -sub getResponseIdString { - my $self = shift; - return "Survey-".$self->get("Survey_id")."-ResponseId"; -} - - -#------------------------------------------------------------------- -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; -} - -#------------------------------------------------------------------- -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; -} - -#------------------------------------------------------------------- - -=head2 prepareView ( ) - -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; -} - - -#------------------------------------------------------------------- -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; - 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"))); - return $self->export($filename,$content); -} - -#------------------------------------------------------------------- -sub export{ - my $self = shift; - my $filename = shift; - $filename =~ s/[^\w\d\.]/_/g; - my $content = shift; - #Create a temporary directory to store files if it doesn't already exist - my $store = WebGUI::Storage->createTemp( $self->session ); - 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"; - } - print TEMP $content; - close TEMP; - my $fileurl = $store->getUrl($filename); - - $self->session->http->setRedirect($fileurl); - - 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"); - - 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; - } - - 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 ""; -} - - -#------------------------------------------------------------------- -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")); -} - -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..58ca2c8d9 --- /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; + + 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/Workflow/Activity/ArchiveOldThreads.pm b/lib/WebGUI/Workflow/Activity/ArchiveOldThreads.pm index 09f593f99..ec9b9a02c 100644 --- a/lib/WebGUI/Workflow/Activity/ArchiveOldThreads.pm +++ b/lib/WebGUI/Workflow/Activity/ArchiveOldThreads.pm @@ -78,7 +78,7 @@ sub execute { my $archiveDate = $epoch - $cs->get("archiveAfter"); my $sql = "select asset.assetId, assetData.revisionDate from Post left join asset on asset.assetId=Post.assetId left join assetData on Post.assetId=assetData.assetId and Post.revisionDate=assetData.revisionDate - where Post.revisionDate ? and assetData.status='archived' and asset.state='published' and Post.threadId=Post.assetId and asset.lineage like ?"; my $b = $self->session->db->read($sql,[$archiveDate, $cs->get("lineage").'%']); while (my ($id, $version) = $b->array) { @@ -87,7 +87,7 @@ sub execute { foreach my $post (@{$thread->getPosts}) { $archiveIt = 0 if (defined $post && $post->get("revisionDate") > $archiveDate); } - $thread->archive if ($archiveIt); + $thread->unarchive if ($archiveIt); } $b->finish; } 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 000000000..d8072b855 Binary files /dev/null and b/www/extras/wobject/Survey/bg-fader-500.gif differ diff --git a/www/extras/wobject/Survey/bg-fader.gif b/www/extras/wobject/Survey/bg-fader.gif new file mode 100644 index 000000000..7db8eb72c Binary files /dev/null and b/www/extras/wobject/Survey/bg-fader.gif differ 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 000000000..cefdab036 Binary files /dev/null and b/www/extras/wobject/Survey/gradient-glossy.png differ diff --git a/www/extras/wobject/Survey/survey.css b/www/extras/wobject/Survey/survey.css new file mode 100644 index 000000000..6baeb76f0 --- /dev/null +++ b/www/extras/wobject/Survey/survey.css @@ -0,0 +1,85 @@ +body { + margin: 0; + background-repeat: repeat-y; + background-position: 0px 0px; +} +.header { + width: 80%; + height: 20px; + margin-left: 80px; +} +#survey { + margin-left: 80px; + width: 85%; +} + +div.dateanswer { + min-height: 250px; +} +div.slider-bg { + position: relative; + background:url(/extras/wobject/Survey/bg-fader-500.gif) 5px 0 no-repeat; + height:68px; + width:529px; +} +div.slider-thumb { + cursor:default; + position: absolute; + top: 30px; + left: 4px; +} +div.slider-min-thumb { + cursor:default; + position: absolute; + top: 4px; +} +div.slider-max-thumb { + cursor:default; + position: absolute; + top: 4px; +} +#headertitle { + display: none; +} +#headertext { + display: none; +} +#questions { + display: none; +} +input.mcbutton{ + font-size: 10px; + font-weight: bold; + text-decoration: none; + background-color: #CCCCCC; + background-repeat: repeat-x; + text-align: center; + display: block; + margin: 0.5em; + padding: .8em; + width: 60px; + font-family: Verdana, Arial, Helvetica, sans-serif; + color: #000000; + background-image: url(/extras/wobject/Survey/gradient-glossy.png); +} +input.mcbutton:hover{ + background-color: #B6D2F1; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 10px; + color: #000000; +} +input.mcbutton-selected{ + background-color: #172D9D; + background-repeat: repeat-x; + color: #FFFFFF; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 10px; + margin: 0.5em; + padding: .8em; + width: 60px; + text-align: center; + display: block; + font-weight: bold; + background-image: url(/extras/wobject/Survey/gradient-glossy.png); + background-position: 0px 0px; +} diff --git a/www/extras/wobject/Survey/surveyedit.css b/www/extras/wobject/Survey/surveyedit.css new file mode 100644 index 000000000..0050e6c20 --- /dev/null +++ b/www/extras/wobject/Survey/surveyedit.css @@ -0,0 +1,132 @@ + +div.testarea { + width: 200px; + height: 100px; + z-index: 999; + border: 1px solid gray; + background: #f7f7f7; + position: absolute; + top: 5%; + left:5%; +} + +div.trashcan { + border: 1px solid gray; + width: 175px; + height: 50px; +} +div.workarea { + padding:10px; + padding-top:40px; + float:left +} + +div.editarea { + margin-top:40px; + padding:10px; + float:left; + border: 1px solid gray; +} + +div.editquestion { + padding:10px; + float:left; +} +div.editanswer { + padding:10px; + float:left; +} + +#submitbutton { padding:20px; } + +div.entry { + padding-bottom:10px; + padding-left:10px; +} + +ul.draglist { + position: relative; + width: 340px; + background: #f7f7f7; + border: 1px solid gray; + list-style: none; + margin:0; + padding:0; + padding-bottom:20px; +} + +ul.draglist li { + margin: 5px; +} + +ul.questionList { + position: relative; + background: #f7f7f7; + border: 1px solid gray; + list-style: none; + margin:0; + padding:0; + min-height: 40px +} + +li.section { + background-color: #CCCCFF; + border:1px solid #7EA6B2; + cursor: move; + min-height: 10px; +} + +li.ssection { + background-color: #E76300; + border:1px solid #7EA6B2; + cursor: move; + min-height: 10px; +} + +li.squestion { + background-color: #CC6600; + border:1px solid #7EA6B2; + cursor: move; + padding-left:15px; + width: 80%; + min-height: 10px; +} +li.newQuestion { +# background-color: #D1E6EC; +# border:1px solid #7EA6B2; +# cursor: move; + padding-left:25px; +} + +li.question { + background-color: #D1E6EC; + border:1px solid #7EA6B2; + cursor: move; + padding-left:15px; + width:80%; + min-height: 10px; +} + +li.answer { + background-color: #D1E6EC; + border:1px solid #7EA6B2; + cursor: move; + padding-left:50px; + width:60%; + min-height: 10px; +} +li.sanswer { + background-color: #CC6600; + border:1px solid #7EA6B2; + cursor: move; + padding-left:50px; + width:60%; + min-height: 10px; +} +li.newAnswer { +# background-color: #D1E6EC; +# border:1px solid #7EA6B2; + padding-left:50px; +# cursor: move; +} + diff --git a/www/extras/wobject/Survey/thumb-n.gif b/www/extras/wobject/Survey/thumb-n.gif new file mode 100644 index 000000000..c91a33293 Binary files /dev/null and b/www/extras/wobject/Survey/thumb-n.gif differ