diff --git a/conf/localOverrides.conf.dist b/conf/localOverrides.conf.dist index c1152042df..0fce400f38 100644 --- a/conf/localOverrides.conf.dist +++ b/conf/localOverrides.conf.dist @@ -330,5 +330,16 @@ $problemDefaults{max_attempts} = -1; #$session_management_via = "session_cookie"; +################################################################################ +# Achievement Facebook Integration +################################################################################ + +## Because of the way facebook works, in order to use facebook integration +## with webwork, you will need to create a facebook "app" specific to the +## domain name of the server you are running. Once you have created the app +## you can enable facebook integration by setting the variables below + +#$allowFacebooking = 1; +#$facebookAppId = your_app_id_here; 1; #final line of the file to reassure perl that it was read properly. diff --git a/htdocs/js/lib/vendor/bootstrap/js/bootstrap.popover.css b/htdocs/js/lib/vendor/bootstrap/js/bootstrap.popover.css new file mode 100644 index 0000000000..36132ce019 --- /dev/null +++ b/htdocs/js/lib/vendor/bootstrap/js/bootstrap.popover.css @@ -0,0 +1,37 @@ +`/*! + * Bootstrap v2.3.1 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ +.clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0;} +.clearfix:after{clear:both;} +.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;} +.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} +.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:0.8;filter:alpha(opacity=80);} +.tooltip.top{margin-top:-3px;padding:5px 0;} +.tooltip.right{margin-left:3px;padding:0 5px;} +.tooltip.bottom{margin-top:3px;padding:5px 0;} +.tooltip.left{margin-left:-3px;padding:0 5px;} +.tooltip-inner{max-width:200px;padding:8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} +.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid;} +.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000000;} +.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000;} +.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000;} +.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000;} +.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#ffffff;-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);white-space:normal;}.popover.top{margin-top:-10px;} +.popover.right{margin-left:10px;} +.popover.bottom{margin-top:10px;} +.popover.left{margin-left:-10px;} +.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0;}.popover-title:empty{display:none;} +.popover-content{padding:9px 14px;} +.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid;} +.popover .arrow{border-width:11px;} +.popover .arrow:after{border-width:10px;content:"";} +.popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0, 0, 0, 0.25);bottom:-11px;}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#ffffff;} +.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0, 0, 0, 0.25);}.popover.right .arrow:after{left:1px;bottom:-10px;border-left-width:0;border-right-color:#ffffff;} +.popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0, 0, 0, 0.25);top:-11px;}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#ffffff;} +.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0, 0, 0, 0.25);}.popover.left .arrow:after{right:1px;border-right-width:0;border-left-color:#ffffff;bottom:-10px;} \ No newline at end of file diff --git a/htdocs/themes/math4/math4.css b/htdocs/themes/math4/math4.css index 0ede97b21f..e9817bfe6a 100644 --- a/htdocs/themes/math4/math4.css +++ b/htdocs/themes/math4/math4.css @@ -357,8 +357,10 @@ table.attemptResults { border-width: 1px; margin-bottom: 1em; border-spacing: 1px; +/* removed float stuff because none of the other elements nearby are + floated and it was causing trouble float:left; - clear:right; + clear:right; */ } table.attemptResults td, @@ -659,7 +661,6 @@ table caption{ #render-modal.modal { width:1024px; left:25%; - top:40%; } #render-modal .modal-body { @@ -802,12 +803,8 @@ table#grades_table pre{ width:60px; } -.tabberlive { - margin-bottom:1ex; -} - -.tabbertab { - min-height:2em; +.tab-pane { + margin-bottom:10px; } .small-table-text, diff --git a/htdocs/themes/math4/math4.js b/htdocs/themes/math4/math4.js index a969eea293..63824bc875 100644 --- a/htdocs/themes/math4/math4.js +++ b/htdocs/themes/math4/math4.js @@ -30,6 +30,7 @@ $(function(){ $('.viewOptions label:has(input:radio)').addClass('radio'); $('label.radio').nextUntil(':not(br)').remove(); $('.viewOptions input:submit').addClass('btn-small'); + $('.facebookbox input:submit').addClass('btn-small'); //Reformats the problem_set_table. $('#problem-sets-form').addClass('form-inline'); @@ -133,4 +134,15 @@ $(function(){ $('#mainform select[name=mydisplayMode]').addClass('input-small').removeClass('input-xxlarge'); $('#mainform select[name=max_shown]').addClass('input-small').removeClass('input-xxlarge'); + //Change tabber tabs to twitter tabs + if ($('div.tabber').length > 0) {tabberAutomatic({});} + $('ul.tabbernav').removeClass('tabbernav').addClass('old-tabber nav nav-tabs'); + $('ul.old-tabber li a').each(function () { $(this).attr('href','#'+$(this).attr('title')).attr('data-toggle','tab');}); + $('div.tabberlive').removeClass('tabberlive').addClass('tab-content'); + $('div.tabbertab').each(function() { $(this).removeClass('tabbertab').addClass('tab-pane').attr('id',$(this).find('h3').html())}); + $('div.tab-pane h3').remove(); + if ($('li.tabberactive a').length > 0) { + $('li.tabberactive a').tab('show');} + + }) \ No newline at end of file diff --git a/htdocs/themes/math4/system.template b/htdocs/themes/math4/system.template index 258a078ad5..f94b44a93f 100644 --- a/htdocs/themes/math4/system.template +++ b/htdocs/themes/math4/system.template @@ -30,12 +30,14 @@ /images/favicon.ico"/> /js/lib/vendor/bootstrap/css/bootstrap.css"/> /themes/math4/math4.css"/> - + /css/tabber.css"/> @@ -44,6 +46,14 @@ + + + + + <!--#path style="text" text=" : " textonly="1"--> @@ -122,6 +132,14 @@ + +
+ +
+ + + + @@ -129,12 +147,6 @@ - -
- -
- -
diff --git a/lib/WeBWorK/AchievementEvaluator.pm b/lib/WeBWorK/AchievementEvaluator.pm index 422a5623cc..f5c8fc00a6 100644 --- a/lib/WeBWorK/AchievementEvaluator.pm +++ b/lib/WeBWorK/AchievementEvaluator.pm @@ -169,11 +169,11 @@ sub checkForAchievements { } #build the cheevo message. New level messages are slightly different - my $imgSrc; + my $imgSrc = $ce->{server_root_url}; if ($achievement->{icon}) { - $imgSrc = $ce->{courseURLs}->{achievements}."/".$achievement->{icon}; + $imgSrc .= $ce->{courseURLs}->{achievements}."/".$achievement->{icon}; } else { - $imgSrc = $ce->{webworkURLs}->{htdocs}."/images/defaulticon.png"; + $imgSrc .= $ce->{webworkURLs}->{htdocs}."/images/defaulticon.png"; } $cheevoMessage .= CGI::start_div({class=>'cheevopopupouter'}); @@ -193,12 +193,12 @@ sub checkForAchievements { } #if facebook integration is enables then create a facebook popup - if ($globalUserAchievement->facebooker) { + if ($ce->{allowFacebooking}&& $globalUserAchievement->facebooker) { $cheevoMessage .= CGI::div({id=>'fb-root'},''); $cheevoMessage .= CGI::script({src=>'http://connect.facebook.net/en_US/all.js'},''); $cheevoMessage .= CGI::start_script(); - #WCU specific appID - $cheevoMessage .= "FB.init({appId:'193051384078348', cookie:true,status:true, xfbml:true });\n"; + + $cheevoMessage .= "FB.init({appId:'".$ce->{facebookAppId}."', cookie:true,status:true, xfbml:true });\n"; my $facebookmessage; if ($achievement->category eq 'level') { diff --git a/lib/WeBWorK/ContentGenerator/Achievements.pm b/lib/WeBWorK/ContentGenerator/Achievements.pm index c61a355c1c..4bec2795c6 100644 --- a/lib/WeBWorK/ContentGenerator/Achievements.pm +++ b/lib/WeBWorK/ContentGenerator/Achievements.pm @@ -60,49 +60,57 @@ sub initialize { } - -sub options { - my ($self) = @_; + sub if_can { + my ($self, $arg) = @_; my $r = $self->r; my $db = $r->db; my $ce = $r->ce; my $authz = $r->authz; my $globalUserAchievement = $self->{globalData}; - #Print the facebook sidepane. This allows users to turn facebook integration on and off. + if ($arg eq 'options' && (not $ce->{allowFacebooking} || not defined($globalUserAchievement))) { + return 0; + } else { + return $self->SUPER::if_can($arg); + } + } - if (defined($globalUserAchievement)) { - - my $changeFacebooking = $r->param('changeFacebooking'); - - if ($changeFacebooking) { - $globalUserAchievement->facebooker(!$globalUserAchievement->facebooker); - $db->putGlobalUserAchievement($globalUserAchievement); - } +sub options { + my ($self) = @_; + my $r = $self->r; + my $db = $r->db; + my $ce = $r->ce; + my $authz = $r->authz; + my $globalUserAchievement = $self->{globalData}; - print CGI::start_center(); + my $changeFacebooking = $r->param('changeFacebooking'); + + if ($changeFacebooking) { + $globalUserAchievement->facebooker(!$globalUserAchievement->facebooker); + $db->putGlobalUserAchievement($globalUserAchievement); + } + + print CGI::start_center(); + print CGI::start_div({class=>'facebookbox'}); + print CGI::start_form(-method=>'POST', -action=>$r->uri); + print $self->hidden_authen_fields; + print CGI::submit('changeFacebooking', $globalUserAchievement->facebooker + ? "Disable Facebook \n Integration" : "Enable Facebook \n Integration"); + print CGI::end_form(); + print CGI::end_div(); + + if ($globalUserAchievement->facebooker) { + #Print Facebook stuff (uses WCU specific appID) print CGI::start_div({class=>'facebookbox'}); - print CGI::start_form(-method=>'POST', -action=>$r->uri); - print $self->hidden_authen_fields; - print CGI::submit('changeFacebooking', $globalUserAchievement->facebooker - ? "Disable Facebook \n Integration" : "Enable Facebook \n Integration"); - print CGI::end_form(); + print CGI::div({id=>'fb-root'},''); + print CGI::script({src=>'http://connect.facebook.net/en_US/all.js'},""); + print CGI::script("FB.init({appId:'".$ce->{facebookAppId}."', cookie:true, status:true, xfbml:true });"); + print ""; + print "Login to FB"; + print ""; print CGI::end_div(); - - if ($globalUserAchievement->facebooker) { - #Print Facebook stuff (uses WCU specific appID) - print CGI::start_div({class=>'facebookbox'}); - print CGI::div({id=>'fb-root'},''); - print CGI::script({src=>'http://connect.facebook.net/en_US/all.js'},""); - print CGI::script("FB.init({appId:'193051384078348', cookie:true, status:true, xfbml:true });"); - print ""; - print "Login to FB"; - print ""; - print CGI::end_div(); - } - print CGI::end_center(); } - + print CGI::end_center(); return ""; } diff --git a/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm b/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm index 2a03e07650..25ed1253d8 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm @@ -245,8 +245,7 @@ sub body { print CGI::p(CGI::b("Any changes made below will be reflected in the achievement for ALL students.")) if $editMode; - print CGI::start_table({}); - print CGI::Tr({}, CGI::td({-colspan=>2}, "Select an action to perform:")); + print CGI::p($r->maketext("Select an action to perform").":"); my @formsToShow; if ($editMode) { @@ -259,6 +258,8 @@ sub body { @formsToShow = @{ EXPORT_FORMS() }; } + print CGI::start_div({-class=>"tabber"}); + my $i = 0; foreach my $actionID (@formsToShow) { @@ -266,10 +267,12 @@ sub body { my $onChange = "document.achievementlist.action[$i].checked=true"; my %actionParams = $self->getActionParams($actionID); - print CGI::Tr({-valign=>"top"}, - CGI::td({}, CGI::input({-type=>"radio", -name=>"action", -value=>$actionID})), - CGI::td({}, $self->$actionForm($onChange, %actionParams)) - ); + print CGI::div({-class=>"tabbertab"}, + CGI::h3($r->maketext(ucfirst(WeBWorK::split_cap($actionID)))), + CGI::span({-class=>"radio_span"}, WeBWorK::CGI_labeled_input(-type=>"radio", + -id=>$actionID."_id", -label_text=>$r->maketext(ucfirst(WeBWorK::split_cap($actionID))), + -input_attr=>{-name=>"action", -value=>$actionID}, -label_attr=>{-class=>"radio_label"})), + $self->$actionForm($onChange, %actionParams)); $i++; } @@ -292,10 +295,11 @@ sub body { ) ); } - print CGI::Tr({}, CGI::td({-colspan=>2, -align=>"center"}, - CGI::submit(-value=>"Take Action!")) - ); - print CGI::end_table(); + + print WeBWorK::CGI_labeled_input(-type=>"reset", -id=>"clear_entries", -input_attr=>{-value=>$r->maketext("Clear"), -class=>"button_input"}); + print WeBWorK::CGI_labeled_input(-type=>"submit", -id=>"take_action", -input_attr=>{-value=>$r->maketext("Take Action!"), -class=>"button_input"}).CGI::br().CGI::br(); + + print CGI::end_div(); ########## print table @@ -1297,6 +1301,13 @@ sub output_JS{ my $site_url = $ce->{webworkURLs}->{htdocs}; print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/addOnLoadEvent.js"}), CGI::end_script(); print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/show_hide.js"}), CGI::end_script(); + print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/tabber.js"}), CGI::end_script(); + + return ""; +} + +# Just tells template to output the stylesheet for Tabber +sub output_tabber_CSS{ return ""; } diff --git a/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm b/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm index 76727894aa..c3c7895991 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm @@ -64,7 +64,7 @@ sub head { print ""; - print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/lib/vendor/jquery-1.7.2.min.js"}), CGI::end_script(); + print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/lib/vendor/jquery-1.8.1.min.js"}), CGI::end_script(); print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/lib/vendor/bootstrap/js/bootstrap.js"}), CGI::end_script(); print CGI::start_script({type=>"text/javascript", src=>$site_url.'/mathjax/MathJax.js?config=TeX-AMS_HTML-full'}), CGI::end_script(); print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/apps/ProblemGrader/problemgrader.js"}), CGI::end_script(); @@ -181,8 +181,6 @@ sub body { ); - my $tthPreambleCache; - return CGI::div({class=>"ResultsWithError"}, CGI::p("You are not authorized to acces the Instructor tools.")) unless $authz->hasPermissions($userID, "access_instructor_tools"); @@ -194,6 +192,7 @@ sub body { my $set = $db->getMergedSet($userID, $setID); # checked my $problem = $db->getMergedProblem($userID, $setID, $problemID); # checked my $user = $db->getUser($userID); + return CGI::div({class=>"ResultsWithError"}, CGI::p("This set needs to be assigned to you before you can grade it.")) unless $set && $problem; return CGI::div({class=>"ResultsWithError"}, CGI::p("This set needs to be assigned to you before you can grade it.")) unless $set && $problem; @@ -268,6 +267,7 @@ sub body { next unless $userProblem; if ($userPastAnswerID && $userProblem) { + my $userPastAnswer = $db->getPastAnswer($userPastAnswerID); my @scores = split(//,$userPastAnswer->scores); my @answers = split(/\t/,$userPastAnswer->answer_string); @@ -298,7 +298,7 @@ sub body { local $ce->{pg}->{specialPGEnvironmentVars}->{problemPreamble}{HTML} = ''; local $ce->{pg}->{specialPGEnvironmentVars}->{problemPostamble}{HTML} = ''; - my $source = "DOCUMENT();\n loadMacros(\"PG.pl\",\"PGbasicmacros.pl\");\n BEGIN_TEXT\n"; + my $source = "DOCUMENT();\n loadMacros(\"PG.pl\",\"PGbasicmacros.pl\",\"contextTypeset.pl\");\n Context(\"Typeset\");\n BEGIN_TEXT\n"; $source .= $answer . "\nEND_TEXT\n ENDDOCUMENT();"; my $pg = WeBWorK::PG->new( $ce, diff --git a/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetList2.pm b/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetList2.pm index d4d6d69075..aa20e9e15d 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetList2.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetList2.pm @@ -2584,7 +2584,7 @@ sub output_JS{ my $ce = $r->ce; my $site_url = $ce->{webworkURLs}->{htdocs}; - print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/jquery-1.7.1.min.js"}), CGI::end_script(); + print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/lib/vendor/jquery-1.8.1.min.js"}), CGI::end_script(); print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/jquery-ui-1.8.18.custom.min.js"}), CGI::end_script(); print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/jquery-ui-timepicker-addon.js"}), CGI::end_script(); print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/addOnLoadEvent.js"}), CGI::end_script(); diff --git a/lib/WeBWorK/DB.pm b/lib/WeBWorK/DB.pm index 4660c494ff..fb3706373c 100644 --- a/lib/WeBWorK/DB.pm +++ b/lib/WeBWorK/DB.pm @@ -1355,6 +1355,12 @@ sub deleteGlobalUserAchievement { # userAchievementID can be undefined if being called from this package my $U = caller eq __PACKAGE__ ? "!" : ""; my ($self, $userID) = shift->checkArgs(\@_, "user_id$U"); + + my @achievements = $self->listUserAchievements($userID); + foreach my $achievement (@achievements) { + $self->deleteUserAchievement($userID,$achievement); + } + if ($self->{global_user_achievement}){ return $self->{global_user_achievement}->delete($userID); } else {