- Add Bolt admin page

- added "hidden" flag to courses


svn path=/trunk/boinc/; revision=14660
This commit is contained in:
David Anderson 2008-02-01 23:11:09 +00:00
parent bda057588a
commit 904cbe5a4f
10 changed files with 217 additions and 58 deletions

View File

@ -81,3 +81,21 @@ David Jan 31 2008
bolt_sched.php
bolt.phph
bolt_compare.php
David Feb 1 2008
- Add Bolt admin page
- added "hidden" flag to courses
db/
bolt_schema.sql
html/
inc/
bolt_db.inc
bolt_ex.inc
util.inc
util_ops.inc
ops/
bolt_ops.php
user/
bolt.php
bolt_sched.php

View File

@ -2,9 +2,9 @@ create table bolt_user (
user_id integer not null,
birth_year integer not null,
sex tinyint not null,
debug tinyint not null,
-- if nonzero, print debug info everywhere
flags integer not null,
attrs text not null,
-- project-defined. Use JSON.
primary key (user_id)
);
@ -15,6 +15,7 @@ create table bolt_course (
name varchar(255) not null,
description text not null,
doc_file varchar(255) not null,
hidden tinyint not null,
primary key (id)
);

View File

@ -25,6 +25,10 @@ define('BOLT_ACTION_COURSE_HOME', 5);
define('BOLT_ACTION_REVIEW', 6);
define('BOLT_ACTION_REPEAT', 7);
// bits in bolt_user.flags
define('BOLT_FLAGS_DEBUG', 1); // print debugging info in output pages
define('BOLT_FLAGS_SHOW_ALL', 2); // show hidden courses
class BoltDb extends DbConn {
static $instance;
@ -108,6 +112,10 @@ class BoltCourse {
$db = BoltDb::get();
return $db->enum('bolt_course', 'BoltCourse');
}
function update($clause) {
$db = BoltDb::get();
return $db->update($this, 'bolt_course', $clause);
}
}
class BoltEnrollment {
@ -197,6 +205,12 @@ class BoltRefreshRec {
$db = BoltDb::get();
return $db->replace('bolt_refresh', $clause);
}
function insert($clause) {
$db = BoltDb::get();
$ret = $db->insert('bolt_refresh', $clause);
if (!$ret) return null;
return $db->insert_id();
}
static function enum($clause) {
$db = BoltDb::get();
return $db->enum('bolt_refresh', 'BoltRefreshRec', $clause);

View File

@ -50,10 +50,19 @@ function bolt_exclusive_choice($choices) {
$i = 0;
start_table();
foreach ($choices as $choice) {
$x = "";
if ($response == $i) $x .= "(You chose this) ";
if ($choice == $right_ans) $x .= "(Right answer)";
row2($choice, $x);
$x = "<td><br></td>";
if ($response == $i) {
if ($choice == $right_ans) {
$x = "<td bgcolor=#88ff88>Right</a>";
} else {
$x = "<td bgcolor=#ff8888>You chose this answer</a>";
}
} else {
if ($choice == $right_ans) {
$x = "<td>Right answer</td>";
}
}
echo "<tr><td width=50% class=fieldname>$choice $x </tr>";
$i++;
}
end_table();
@ -109,7 +118,10 @@ function bolt_inclusive_choice($choices) {
$response = isset($$key);
$r = $choice[1];
$correct = ($r && $response) || (!$r && !$response);
table_row($c, $r?"yes":"no", $response?"yes":"no");
$color = $correct?"#88ff88":"#ff8888";
table_row($c, $r?"yes":"no",
array($response?"yes":"no", "bgcolor=$color")
);
$i++;
}
end_table();

View File

@ -19,7 +19,6 @@ class BoltExerciseSet extends BoltRandom {
global $user;
global $refresh;
echo "XSET_CALLBACK: $score";
$nav_info = null;
$state_rec = $iter->state[$this->name];
$nshown = $state_rec['nshown'];
@ -27,7 +26,6 @@ class BoltExerciseSet extends BoltRandom {
$iter->state[$this->name] = $state_rec;
$is_last = ($nshown+1 == $this->ntoshow);
if (!$is_last) {
echo "XSET_CALLBACK: not done";
return false;
}
@ -41,7 +39,6 @@ class BoltExerciseSet extends BoltRandom {
}
$avg_score = $total_score/($nshown+1);
echo "XSET_CALLBACK: avg $avg_score";
$repeat = null;
$least = 1;
foreach ($this->repeats as $r) {

View File

@ -127,7 +127,7 @@ function show_login($user) {
//
if (!function_exists("page_head")){
function page_head($title, $java_onload=null, $title_plain=null, $prefix="") {
$styleSheet = URL_BASE.STYLESHEET;
$stylesheet = URL_BASE.STYLESHEET;
$rssname = PROJECT . " RSS 2.0";
$rsslink = URL_BASE."rss_main.php";
@ -142,7 +142,7 @@ function page_head($title, $java_onload=null, $title_plain=null, $prefix="") {
} else {
echo "<html><head><title>".strip_tags($title_plain)."</title>\n";
}
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"$styleSheet\">
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"$stylesheet\">
<link rel=\"alternate\" type=\"application/rss+xml\" title=\"$rssname\" href=\"$rsslink\">
</head>
";

View File

@ -1,41 +1,36 @@
<?php
$cvs_version_tracker[]="\$Id$"; //Generated automatically - do not edit
require_once("../inc/db_ops.inc");
require_once("../inc/util.inc");
require_once("../project/project.inc");
define("EMAIL_EXISTS", -1);
define("EMAIL_UPDATED", 1);
define("EMAIL_FAIL", -2);
define("LG_FONT", "<font size=\"+1\">");
define("SM_FONT", "<font size=\"-1\">");
// TODO: get rid of the following. use style sheets
define("TD", "<td bgcolor=\"#708090\">");
define("TD2", "<td colspan=\"2\" bgcolor=\"#708090\">");
define("TD3", "<td colspan=\"3\" bgcolor=\"#708090\">");
define("TABLE", "<table cellpadding=\"8\" border=\"1\" width=\"100%\">");
define("TABLE2", "<table width=\"580\">");
define("TITLE_COLOR", " bgcolor=\"#000000\" ");
define("TITLE_FONT", " <font color=\"#ffffff\"> ");
define("BODY_COLOR", " bgcolor=\"#ffffff\" ");
define("NOLOGIN", "Not logged in. Click <a href=\"login.php\">here</a> to login.\n");
function admin_page_head($title) {
//TODO: Add DOCTYPE description here when ready for HTML 4.01
echo "<html><head><title>$title</title></head><body " . BODY_COLOR . ">\n";
echo TABLE . "<tr " . TITLE_COLOR . "><td>" . TITLE_FONT . "<font size=\"6\"><b><a href=\"index.php\">".PROJECT.":</a> $title</b></font></td></tr></table>\n";
$stylesheet = URL_BASE.STYLESHEET;
echo "<html><head><title>$title</title>
<link rel=\"stylesheet\" type=\"text/css\" href=\"$stylesheet\">
</head>
<body bgcolor=\"#ffffff\">
<h2>".PROJECT.": $title</h2>
";
}
function admin_page_tail() {
echo "<br><hr noshade size=1><center>";
echo "<a href=\"index.php\"> Back to Main admin page </a></center>\n";
echo "</body>\n</html>";
echo "<br><hr noshade size=1><center>
<a href=\"index.php\"> Back to Main admin page </a></center>
</body></html>
";
}
// TODO: get rid of all the following
function print_checkbox($text,$name,$checked) {
echo "<input type=\"checkbox\" name=\"$name\""
. (strlen($checked) ? " checked=\"checked\"" : "") . ">"
@ -71,4 +66,5 @@ function show_profile_link_ops($user) {
}
}
$cvs_version_tracker[]="\$Id$"; //Generated automatically - do not edit
?>

114
html/ops/bolt_ops.php Normal file
View File

@ -0,0 +1,114 @@
<?php
require_once("../inc/bolt_db.inc");
require_once("../inc/util_ops.inc");
function show_course($course) {
echo "<tr>
<td>Name: $course->name<br>Description: $course->description<br>Created: ".date_str($course->create_time)."</td>
<td>$course->doc_file</td>
<td>
";
if ($course->hidden) {
show_button("bolt_ops.php?action=unhide&course_id=$course->id", "Unhide", "Unhide this course");
} else {
show_button("bolt_ops.php?action=hide&course_id=$course->id", "Hide", "Hide this course");
}
}
function show_courses() {
$courses = BoltCourse::enum();
start_table();
row1("Existing courses", 3);
table_header("Name/description", "Course document", "");
foreach ($courses as $course) {
show_course($course);
}
end_table();
}
function add_course_form() {
echo "
<form action=bolt_ops.php method=get>
";
start_table();
row1("Add course");
row2("Name<span class=note><br>Visible to users</span>", "<input name=course_name>");
row2("Internal name<span class=note><br>Not visible to users; used as a directory name, so no spaces or special chars</span>", "<input name=short_name>");
row2("Description<span class=note><br>Visible to users</span>", "<textarea name=description cols=60></textarea>");
row2("Course document", "<input name=doc_file>");
row2("", "<input type=submit name=submit value=\"Create course\">");
end_table();
echo "</form>";
}
function user_settings() {
global $user;
$flags = $user->bolt->flags;
echo "<form action=bolt_ops.php method=get>";
start_table();
row1("User settings");
$x = ($flags&BOLT_FLAGS_SHOW_ALL)?"checked":"";
row2("Show hidden courses?", "<input type=checkbox name=show_all $x>");
$x = ($flags&BOLT_FLAGS_DEBUG)?"checked":"";
row2("Show debugging output?", "<input type=checkbox name=debug $x>");
row2("", "<input type=submit name=submit value=\"Update user\">");
end_table();
echo "</form>";
}
function show_all() {
admin_page_head("Bolt course administration");
show_courses();
echo "<p>";
add_course_form();
echo "<p>";
user_settings();
admin_page_tail();
}
$user = get_logged_in_user();
BoltUser::lookup($user);
$submit = get_str('submit', true);
if ($submit == 'Create course') {
$short_name = get_str('short_name');
$name = get_str('course_name');
$description = get_str('description');
$doc_file = get_str('doc_file');
$now = time();
BoltCourse::insert("(create_time, short_name, name, description, doc_file) values ($now, '$short_name', '$name', '$description', '$doc_file')");
Header('Location: bolt_ops.php');
exit();
} else if ($submit == 'Update user') {
$flags = 0;
if (get_str('show_all', true)) $flags |= BOLT_FLAGS_SHOW_ALL;
if (get_str('debug', true)) $flags |= BOLT_FLAGS_DEBUG;
$user->bolt->update("flags=$flags");
$user->bolt->flags = $flags;
Header('Location: bolt_ops.php');
exit();
} else {
$action = get_str('action', true);
if ($action) {
$course_id = get_int('course_id');
$course = BoltCourse::lookup_id($course_id);
if (!$course) error_page("no such course");
switch ($action) {
case 'hide':
$course->update("hidden=1");
break;
case 'unhide':
$course->update("hidden=0");
break;
default:
error_page("unknown action $action");
}
Header('Location: bolt_ops.php');
exit();
}
}
show_all();
?>

View File

@ -6,6 +6,7 @@ require_once("../inc/util.inc");
page_head("Courses");
$user = get_logged_in_user(true);
BoltUser::lookup($user);
$courses = BoltCourse::enum();
start_table();
@ -13,6 +14,9 @@ table_header(
"Course", "Status"
);
foreach ($courses as $course) {
if ($course->hidden && !($user->bolt->flags&BOLT_FLAG_SHOW_ALL)) {
continue;
}
$e = $user?BoltEnrollment::lookup($user->id, $course->id):null;
if ($e) {
$start = date_str($e->create_time);
@ -22,9 +26,13 @@ foreach ($courses as $course) {
$status = "Started $start
<br>Last visit: $ago ago
<br>$pct% done
<br><a href=bolt_sched.php?course_id=$course->id&action=resume>Resume</a>
";
if ($view->fraction_done < 1) {
$status .= "<br><a href=bolt_sched.php?course_id=$course->id&action=resume>Resume</a>
";
}
$status .= "<br><a href=bolt_sched.php?course_id=$course->id&action=start>Restart</a>
<br><a href=bolt_course.php?course_id=$course->id>History</a>
<br><a href=bolt_sched.php?course_id=$course->id&action=start>Restart</a>
";
} else {
$status = "

View File

@ -56,7 +56,7 @@ function create_view($iter, $mode, $prev_view_id) {
$item->name = '--end--';
}
$state = $iter->encode_state();
if ($user->bolt->debug) {
if ($user->bolt->flags&BOLT_FLAGS_DEBUG) {
echo "<pre>Ending state: "; print_r($iter->state); echo "</pre>\n";
}
return BoltView::insert("(user_id, course_id, item_name, start_time, mode, state, fraction_done, prev_view_id) values ($user->id, $course->id, '$item->name', $now, $mode, '$state', $iter->frac_done, $prev_view_id)");
@ -71,17 +71,9 @@ function show_finished_page($view_id, $prev_view_id) {
page_head(null);
if (function_exists('bolt_header')) bolt_header("Course completed");
echo "Congratulations - you have completed this course.";
$prev = "<a href=bolt_sched.php?$url_args&action=prev&view_id=$view_id><< Prev</a>";
echo "
<p>
<center>
<table width=60%><tr>
<td width=33% align=left>$prev</td>
<td width=33% align=center><a href=bolt.php>Up</a></td>
<td width=33% align=right></td>
</table>
</center>
";
$links[] = "<a href=bolt_sched.php?$url_args&action=prev&view_id=$view_id><img src=img/prev.gif></a>";
$up_link = "<a href=bolt_sched.php?$url_args&action=course_home&view_id=$view_id>Course home page</a>";
show_nav($links, $up_link);
if (function_exists('bolt_footer')) bolt_footer();
}
@ -101,9 +93,14 @@ function show_nav($links, $up_link) {
echo "<td align=center>$link</td>";
}
echo "</tr></table> </center>
$up_link
<hr>
Question or comment?
<br>
<textarea cols=60></textarea>
<br>
<input type=submit value=Ask>
<p>
question link
$up_link
";
}
@ -126,10 +123,10 @@ function show_item($iter, $view_id, $prev_view_id, $mode, $repeat=null) {
$links = array();
if ($prev_view_id) {
$links[] = "<a href=bolt_sched.php?$url_args&action=prev&view_id=$view_id><< Prev</a>";
$links[] = "<a href=bolt_sched.php?$url_args&action=prev&view_id=$view_id><img src=img/prev.gif></a>";
}
$next = "<a href=bolt_sched.php?$url_args&action=next&view_id=$view_id>Next >></a>";
$next = "<a href=bolt_sched.php?$url_args&action=next&view_id=$view_id><img src=img/next.gif></a>";
if ($item->is_exercise()) {
$bolt_ex_mode = $mode;
@ -150,13 +147,13 @@ function show_item($iter, $view_id, $prev_view_id, $mode, $repeat=null) {
srand($view_id);
require($item->filename);
if (function_exists('bolt_divide')) bolt_divide();
$next = "<input type=submit value=OK></form>";
$next = "<input type=image src=img/next.gif value=OK></form>";
break;
case BOLT_MODE_ANSWER:
require($item->filename);
if (function_exists('bolt_divide')) bolt_divide();
$score_pct = number_format($bolt_ex_score*100);
echo "Score: $score_pct%";
echo "Your score: $score_pct%";
break;
}
} else {
@ -184,7 +181,7 @@ function show_item($iter, $view_id, $prev_view_id, $mode, $repeat=null) {
$links[] = $next;
}
$up_link = "<a href=bolt_sched.php?$url_args&action=course_home&view_id=$view_id>Up</a>";
$up_link = "<a href=bolt_sched.php?$url_args&action=course_home&view_id=$view_id>Course home page</a>";
show_nav($links, $up_link);
if (function_exists('bolt_footer')) bolt_footer();
@ -310,6 +307,7 @@ case 'start_confirm':
case 'update_info':
update_info();
start_course();
break;
case 'prev':
$view = finalize_view($view_id, BOLT_ACTION_PREV);
if ($view->prev_view_id) {
@ -329,13 +327,13 @@ case 'next': // "next" button in lesson or exercise answer page
$iter = new BoltIter($course_doc);
$iter->decode_state($view->state);
if ($user->bolt->debug) {
if ($user->bolt->flags&BOLT_FLAGS_DEBUG) {
echo "<pre>Initial state: "; print_r($iter->state); echo "</pre>\n";
}
$iter->next();
if ($user->bolt->debug) {
if ($user->bolt->flags&BOLT_FLAGS_DEBUG) {
echo "<pre>Item: "; print_r($iter->item); echo "</pre>\n";
}
if ($iter->item) {
@ -361,12 +359,12 @@ case 'answer': // submit answer in exercise
$view = finalize_view($view_id, BOLT_ACTION_SUBMIT);
$iter = new BoltIter($course_doc);
$iter->decode_state($view->state);
if ($user->bolt->debug) {
if ($user->bolt->flags&BOLT_FLAGS_DEBUG) {
echo "<pre>Initial state:"; print_r($iter->state); echo "</pre>\n";
}
$iter->at();
if ($user->bolt->debug) {
if ($user->bolt->flags&BOLT_FLAGS_DEBUG) {
echo "<pre>Item: "; print_r($iter->item); echo "</pre>\n";
}
$item = $iter->item;
@ -419,7 +417,7 @@ case 'answer': // submit answer in exercise
$refresh->update("create_time=$now, xset_result_id=$id, due_time=$due_time");
} else {
BoltRefreshRec::insert(
"user_id=$user->id, course_id=$course->id, name='$this->name', create_time=$now, xset_result_id=$id, due_time=$due_time"
"(user_id, course_id, name, create_time, xset_result_id, due_time) values ($user->id, $course->id, '$xset->name', $now, $id, $due_time)"
);
}
}
@ -429,6 +427,7 @@ case 'answer': // submit answer in exercise
srand($view_id);
$view_id = create_view($iter, BOLT_MODE_ANSWER, $view->id);
$repeat = null;
show_item($iter, $view_id, $view->id, BOLT_MODE_ANSWER, $repeat);
break;
case 'answer_page':