Updating LTI submission viewer
authorChris Scribner <scriby@gmail.com>
Wed, 28 Sep 2011 15:11:20 +0000 (11:11 -0400)
committerChris Scribner <scriby@gmail.com>
Mon, 7 Nov 2011 01:41:54 +0000 (20:41 -0500)
mod/lti/db/access.php
mod/lti/db/install.xml
mod/lti/grade.php [moved from mod/lti/submissions.php with 63% similarity]
mod/lti/lib.php
mod/lti/locallib.php
mod/lti/service.php
mod/lti/servicelib.php
mod/lti/submissions.js [new file with mode: 0644]
mod/lti/view.php

index cfedb54..3006bb9 100644 (file)
@@ -44,7 +44,7 @@
 
 $capabilities = array(
 
-    'mod/ltii:view' => array(
+    'mod/lti:view' => array(
 
         'captype' => 'read',
         'contextlevel' => CONTEXT_MODULE,
index f606a69..18765ee 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="mod/lti/db" VERSION="20110901" COMMENT="XMLDB file for Moodle mod/lti"
+<XMLDB PATH="mod/lti/db" VERSION="20110923" COMMENT="XMLDB file for Moodle mod/lti"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
 >
@@ -58,7 +58,7 @@
         <INDEX NAME="tooldomain" UNIQUE="false" FIELDS="tooldomain" PREVIOUS="course"/>
       </INDEXES>
     </TABLE>
-    <TABLE NAME="lti_types_config" COMMENT="Basic LTI types configuration" PREVIOUS="lti_types">
+    <TABLE NAME="lti_types_config" COMMENT="Basic LTI types configuration" PREVIOUS="lti_types" NEXT="lti_submission">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="typeid"/>
         <FIELD NAME="typeid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Basic LTI type id" PREVIOUS="id" NEXT="name"/>
         <INDEX NAME="typeid" UNIQUE="false" FIELDS="typeid"/>
       </INDEXES>
     </TABLE>
+    <TABLE NAME="lti_submission" COMMENT="Keeps track of individual submissions for LTI activities." PREVIOUS="lti_types_config">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="ltiid"/>
+        <FIELD NAME="ltiid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="ID of the LTI tool instance" PREVIOUS="id" NEXT="userid"/>
+        <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="ltiid" NEXT="datesubmitted"/>
+        <FIELD NAME="datesubmitted" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="userid" NEXT="dateupdated"/>
+        <FIELD NAME="dateupdated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="datesubmitted" NEXT="gradepercent"/>
+        <FIELD NAME="gradepercent" TYPE="number" LENGTH="10" NOTNULL="true" UNSIGNED="false" SEQUENCE="false" DECIMALS="5" PREVIOUS="dateupdated" NEXT="originalgrade"/>
+        <FIELD NAME="originalgrade" TYPE="number" LENGTH="10" NOTNULL="true" UNSIGNED="false" SEQUENCE="false" DECIMALS="5" PREVIOUS="gradepercent" NEXT="launchid"/>
+        <FIELD NAME="launchid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="originalgrade" NEXT="state"/>
+        <FIELD NAME="state" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="launchid"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+      </KEYS>
+      <INDEXES>
+        <INDEX NAME="ltiid" UNIQUE="false" FIELDS="ltiid"/>
+      </INDEXES>
+    </TABLE>
   </TABLES>
 </XMLDB>
\ No newline at end of file
similarity index 63%
rename from mod/lti/submissions.php
rename to mod/lti/grade.php
index 8482181..866fe19 100644 (file)
@@ -89,4 +89,96 @@ require_login($course, false, $cm);
 
 require_capability('mod/lti:grade', get_context_instance(CONTEXT_MODULE, $cm->id));
 
-lti_submissions($cm, $course, $basiclti, $mode);   // Display or process the submissions
+//lti_submissions($cm, $course, $basiclti, $mode);   // Display or process the submissions
+
+$module = array(
+    'name'      => 'mod_lti_submissions',
+    'fullpath'  => '/mod/lti/submissions.js',
+    'requires'  => array('base'),
+    'strings'   => array(
+        
+    ),
+);
+
+$PAGE->requires->js_init_call('M.mod_lti.submissions.init', array(), true, $module);
+
+$PAGE->requires->yui2_lib('datatable');
+
+$submissionquery = <<<SQL
+    SELECT s.id, u.firstname, u.lastname, u.id AS userid, s.datesubmitted, s.gradepercent
+    FROM {lti_submission} s
+    INNER JOIN {user} u ON s.userid = u.id
+    WHERE s.ltiid = :ltiid
+    ORDER BY s.datesubmitted DESC
+SQL;
+
+$submissions = $DB->get_records_sql($submissionquery, array('ltiid' => $basiclti->id));
+
+$html = <<<HTML
+<noscript>
+    <!-- If javascript is disabled, we need to show the table using CSS.
+        The table starts out hidden to avoid flickering as it loads -->
+    <style type="text/css">
+        #lti_submissions_table_container { display: block !important; }
+    </style>
+</noscript>
+
+<div id="lti_submissions_table_container" style="display:none">
+    <table id='lti_submissions_table'>
+        <thead>
+            <tr>
+                <th>User</th>
+                <th>Date</th>
+                <th>Grade</th>
+            </tr>
+        </thead>
+        <tbody>
+            <!--table body-->
+        </tbody>
+    </table>
+</div>
+HTML;
+
+$rowtemplate = <<<HTML
+<tr>
+    <td>
+        <!--firstname--> <!--lastname-->
+    </td>
+    <td>
+        <!--datesubmitted-->
+    </td>
+    <td>
+        <!--gradepercent-->
+    </td>
+</tr>
+HTML;
+
+$rows = '';
+
+foreach($submissions as $submission){
+    $row = $rowtemplate;
+    
+    foreach($submission as $key => $value){
+        if($key === 'datesubmitted'){
+            $value = userdate($value);
+        }
+        
+        $row = str_replace('<!--' . $key . '-->', $value, $row);
+    }
+    
+    $rows .= $row;
+}
+
+$table = str_replace('<!--table body-->', $rows, $html);
+
+$title = 'Submissions for ' . $basiclti->name;
+
+$PAGE->set_title(format_string($title , true));
+$PAGE->set_heading($course->fullname);
+
+echo $OUTPUT->header();
+echo $OUTPUT->heading($title );
+
+echo $table;
+
+echo $OUTPUT->footer();
\ No newline at end of file
index c1ee7c6..30fc958 100644 (file)
@@ -315,652 +315,6 @@ function lti_get_lti_types() {
     return $DB->get_records('lti_types');
 }
 
-/**
- * Returns Basic LTI types configuration
- *
- * @return array of basicLTI types
- */
-/*function lti_get_types() {
-    $types = array();
-
-    $basicltitypes = lti_get_lti_types();
-    if (!empty($basicltitypes)) {
-        foreach ($basicltitypes as $basicltitype) {
-            $ltitypesconfig = lti_get_type_config($basicltitype->id);
-
-            $modclass = MOD_CLASS_ACTIVITY;
-            if (isset($ltitypesconfig['module_class_type'])) {
-                if ($ltitypesconfig['module_class_type']=='1') {
-                    $modclass = MOD_CLASS_RESOURCE;
-                }
-            }
-
-            $type = new object();
-            $type->modclass = $modclass;
-            $type->type = 'lti&amp;type='.urlencode($basicltitype->rawname);
-            $type->typestr = $basicltitype->name;
-            $types[] = $type;
-        }
-    }
-
-    return $types;
-}*/
-
-//////////////////////////////////////////////////////////////////////////////////////
-/// Any other basiclti functions go here.  Each of them must have a name that
-/// starts with basiclti_
-/// Remember (see note in first lines) that, if this section grows, it's HIGHLY
-/// recommended to move all funcions below to a new "localib.php" file.
-
-///**
-// *
-// */
-//function process_outcomes($userid, $course, $basiclti) {
-//    global $CFG, $USER;
-//
-//    if (empty($CFG->enableoutcomes)) {
-//        return;
-//    }
-//
-//    require_once($CFG->libdir.'/gradelib.php');
-//
-//    if (!$formdata = data_submitted() or !confirm_sesskey()) {
-//        return;
-//    }
-//
-//    $data = array();
-//    $grading_info = grade_get_grades($course->id, 'mod', 'basiclti', $basiclti->id, $userid);
-//
-//    if (!empty($grading_info->outcomes)) {
-//        foreach ($grading_info->outcomes as $n => $old) {
-//            $name = 'outcome_'.$n;
-//            if (isset($formdata->{$name}[$userid]) and $old->grades[$userid]->grade != $formdata->{$name}[$userid]) {
-//                $data[$n] = $formdata->{$name}[$userid];
-//            }
-//        }
-//    }
-//    if (count($data) > 0) {
-//        grade_update_outcomes('mod/basiclti', $course->id, 'mod', 'basiclti', $basiclti->id, $userid, $data);
-//    }
-//
-//}
-
-/**
- * Top-level function for handling of submissions called by submissions.php
- *
- * This is for handling the teacher interaction with the grading interface
- *
- * @global object
- * @param string $mode Specifies the kind of teacher interaction taking place
- */
-function lti_submissions($cm, $course, $basiclti, $mode) {
-    ///The main switch is changed to facilitate
-    ///1) Batch fast grading
-    ///2) Skip to the next one on the popup
-    ///3) Save and Skip to the next one on the popup
-
-    //make user global so we can use the id
-    global $USER, $OUTPUT, $DB;
-
-    $mailinfo = optional_param('mailinfo', null, PARAM_BOOL);
-
-    if (optional_param('next', null, PARAM_BOOL)) {
-        $mode='next';
-    }
-    if (optional_param('saveandnext', null, PARAM_BOOL)) {
-        $mode='saveandnext';
-    }
-
-    if (is_null($mailinfo)) {
-        if (optional_param('sesskey', null, PARAM_BOOL)) {
-            set_user_preference('lti_mailinfo', $mailinfo);
-        } else {
-            $mailinfo = get_user_preferences('lti_mailinfo', 0);
-        }
-    } else {
-        set_user_preference('lti_mailinfo', $mailinfo);
-    }
-
-    switch ($mode) {
-        case 'grade':                         // We are in a main window grading
-            if ($submission = process_feedback()) {
-                lti_display_submissions($cm, $course, $basiclti, get_string('changessaved'));
-            } else {
-                lti_display_submissions($cm, $course, $basiclti);
-            }
-            break;
-
-        case 'single':                        // We are in a main window displaying one submission
-            if ($submission = process_feedback()) {
-                lti_display_submissions($cm, $course, $basiclti, get_string('changessaved'));
-            } else {
-                display_submission();
-            }
-            break;
-
-        case 'all':                          // Main window, display everything
-            lti_display_submissions($cm, $course, $basiclti);
-            break;
-
-        case 'fastgrade':
-            /// do the fast grading stuff - this process should work for all 3 subclasses
-            $grading    = false;
-            $commenting = false;
-            $col        = false;
-            if (isset($_POST['submissioncomment'])) {
-                $col = 'submissioncomment';
-                $commenting = true;
-            }
-            if (isset($_POST['menu'])) {
-                $col = 'menu';
-                $grading = true;
-            }
-            if (!$col) {
-                //both submissioncomment and grade columns collapsed..
-                lti_display_submissions($cm, $course, $basiclti);
-                break;
-            }
-
-            foreach ($_POST[$col] as $id => $unusedvalue) {
-
-                $id = (int)$id; //clean parameter name
-
-                // Get grade item
-                $gradeitem = $DB->get_record('grade_items', array('courseid' => $cm->course, 'iteminstance' => $cm->instance));
-
-                // Get grade
-                $gradeentry = $DB->get_record('grade_grades', array('userid' => $id, 'itemid' => $gradeitem->id));
-
-                $grade = $_POST['menu'][$id];
-                $feedback = trim($_POST['submissioncomment'][$id]);
-
-                if ((!$gradeentry) && (($grade != '-1') || ($feedback != ''))) {
-                    $newsubmission = true;
-                } else {
-                    $newsubmission = false;
-                }
-
-                //for fast grade, we need to check if any changes take place
-                $updatedb = false;
-
-                if ($gradeentry) {
-                    if ($grading) {
-                        $grade = $_POST['menu'][$id];
-                        $updatedb = $updatedb || (($gradeentry->rawgrade != $grade) && ($gradeentry->rawgrade != '-1'));
-                        if ($grade != '-1') {
-                            $gradeentry->rawgrade = $grade;
-                            $gradeentry->finalgrade = $grade;
-                        } else {
-                            $gradeentry->rawgrade = null;
-                            $gradeentry->finalgrade = null;
-                        }
-                    } else {
-                        if (!$newsubmission) {
-                            unset($gradeentry->rawgrade);  // Don't need to update this.
-                        }
-                    }
-
-                    if ($commenting) {
-                        $commentvalue = trim($_POST['submissioncomment'][$id]);
-                        $updatedb = $updatedb || ($gradeentry->feedback != $commentvalue);
-                        // Special case
-                        if (($gradeentry->feedback == null) && ($commentvalue == "")) {
-                            unset($gradeentry->feedback);
-                        }
-                        $gradeentry->feedback = $commentvalue;
-                    } else {
-                        unset($gradeentry->feedback);  // Don't need to update this.
-                    }
-
-                } else { // No previous grade entry found
-                    if ($newsubmission) {
-                        if ($grade != '-1') {
-                            $gradeentry->rawgrade = $grade;
-                            $updatedb = true;
-                        }
-                        if ($feedback != '') {
-                            $gradeentry->feedback = $feedback;
-                            $updatedb = true;
-                        }
-                    }
-                }
-
-                $gradeentry->usermodified    = $USER->id;
-                if (!$gradeentry->timecreated) {
-                    $gradeentry->timecreated = time();
-                }
-                $gradeentry->timemodified = time();
-
-                //if it is not an update, we don't change the last modified time etc.
-                //this will also not write into database if no submissioncomment and grade is entered.
-                if ($updatedb) {
-                    if ($gradeentry->rawgrade == '-1') {
-                        $gradeentry->rawgrade = null;
-                    }
-
-                    if ($newsubmission) {
-                        if (!isset($gradeentry->feedback)) {
-                            $gradeentry->feedback = '';
-                        }
-                        $gradeentry->itemid = $gradeitem->id;
-                        $gradeentry->userid = $id;
-                        $sid = $DB->insert_record("grade_grades", $gradeentry);
-                        $gradeentry->id = $sid;
-                    } else {
-                        $DB->update_record("grade_grades", $gradeentry);
-                    }
-
-                    //add to log only if updating
-                    add_to_log($course->id, 'lti', 'update grades',
-                               'submissions.php?id='.$cm->id.'&user='.$USER->id,
-                               $USER->id, $cm->id);
-                }
-
-            }
-
-            $message = $OUTPUT->notification(get_string('changessaved'), 'notifysuccess');
-
-            lti_display_submissions($cm, $course, $basiclti, $message);
-            break;
-
-        case 'saveandnext':
-            ///We are in pop up. save the current one and go to the next one.
-            //first we save the current changes
-            if ($submission = process_feedback()) {
-                //print_heading(get_string('changessaved'));
-                //$extra_javascript = $this->update_main_listing($submission);
-            }
-
-        case 'next':
-            /// We are currently in pop up, but we want to skip to next one without saving.
-            ///    This turns out to be similar to a single case
-            /// The URL used is for the next submission.
-            $offset = required_param('offset', PARAM_INT);
-            $nextid = required_param('nextid', PARAM_INT);
-            $id = required_param('id', PARAM_INT);
-            $offset = (int)$offset+1;
-            //$this->display_submission($offset+1 , $nextid);
-            redirect('submissions.php?id='.$id.'&userid='. $nextid . '&mode=single&offset='.$offset);
-            break;
-
-        case 'singlenosave':
-            display_submission();
-            break;
-
-        default:
-            echo "Critical error. Something is seriously wrong!!";
-            break;
-    }
-}
-
-/**
- *  Display all the submissions ready for grading
- *
- * @global object
- * @global object
- * @global object
- * @global object
- * @param string $message
- * @return bool|void
- */
-function lti_display_submissions($cm, $course, $basiclti, $message='') {
-    global $CFG, $DB, $OUTPUT, $PAGE;
-    require_once($CFG->libdir.'/gradelib.php');
-
-    /* first we check to see if the form has just been submitted
-     * to request user_preference updates
-     */
-    $updatepref = optional_param('updatepref', 0, PARAM_INT);
-
-    if (isset($_POST['updatepref'])) {
-        $perpage = optional_param('perpage', 10, PARAM_INT);
-        $perpage = ($perpage <= 0) ? 10 : $perpage;
-        $filter = optional_param('filter', 0, PARAM_INT);
-        set_user_preference('lti_perpage', $perpage);
-        set_user_preference('lti_quickgrade', optional_param('quickgrade', 0, PARAM_BOOL));
-        set_user_preference('lti_filter', $filter);
-    }
-
-    /* next we get perpage and quickgrade (allow quick grade) params
-     * from database
-     */
-    $perpage    = get_user_preferences('lti_perpage', 10);
-    $quickgrade = get_user_preferences('lti_quickgrade', 0);
-    $filter = get_user_preferences('lti_filter', 0);
-    $grading_info = grade_get_grades($course->id, 'mod', 'lti', $basiclti->id);
-
-    if (!empty($CFG->enableoutcomes) and !empty($grading_info->outcomes)) {
-        $uses_outcomes = true;
-    } else {
-        $uses_outcomes = false;
-    }
-
-    $page    = optional_param('page', 0, PARAM_INT);
-    $strsaveallfeedback = get_string('saveallfeedback', 'lti');
-
-    $tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet
-    add_to_log($course->id, 'lti', 'view submission', 'submissions.php?id='.$cm->id, $basiclti->id, $cm->id);
-
-    $PAGE->set_title(format_string($basiclti->name, true));
-    $PAGE->set_heading($course->fullname);
-    echo $OUTPUT->header();
-
-    echo '<div class="usersubmissions">';
-
-    //hook to allow plagiarism plugins to update status/print links.
-    plagiarism_update_status($course, $cm);
-
-    /// Print quickgrade form around the table
-    if ($quickgrade) {
-        $formattrs = array();
-        $formattrs['action'] = new moodle_url('/mod/lti/submissions.php');
-        $formattrs['id'] = 'fastg';
-        $formattrs['method'] = 'post';
-
-        echo html_writer::start_tag('form', $formattrs);
-        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'id',      'value'=> $cm->id));
-        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'mode',    'value'=> 'fastgrade'));
-        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'page',    'value'=> $page));
-        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=> sesskey()));
-    }
-
-    $course_context = get_context_instance(CONTEXT_COURSE, $course->id);
-    if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) {
-        echo '<div class="allcoursegrades"><a href="' . $CFG->wwwroot . '/grade/report/grader/index.php?id=' . $course->id . '">'
-            . get_string('seeallcoursegrades', 'grades') . '</a></div>';
-    }
-
-    if (!empty($message)) {
-        echo $message;   // display messages here if any
-    }
-
-    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-
-/// Check to see if groups are being used in this tool
-
-    /// find out current groups mode
-    $groupmode = groups_get_activity_groupmode($cm);
-    $currentgroup = groups_get_activity_group($cm, true);
-    groups_print_activity_menu($cm, $CFG->wwwroot . '/mod/lti/submissions.php?id=' . $cm->id);
-
-    /// Get all ppl that are allowed to submit tools
-    list($esql, $params) = get_enrolled_sql($context, 'mod/lti:view', $currentgroup);
-
-    $sql = "SELECT u.id FROM {user} u ".
-           "LEFT JOIN ($esql) eu ON eu.id=u.id ".
-           "WHERE u.deleted = 0 AND eu.id=u.id ";
-
-    $users = $DB->get_records_sql($sql, $params);
-    if (!empty($users)) {
-        $users = array_keys($users);
-    }
-
-    // if groupmembersonly used, remove users who are not in any group
-    if ($users and !empty($CFG->enablegroupmembersonly) and $cm->groupmembersonly) {
-        if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) {
-            $users = array_intersect($users, array_keys($groupingusers));
-        }
-    }
-
-    $tablecolumns = array('picture', 'fullname', 'grade', 'submissioncomment', 'timemodified', 'timemarked', 'status', 'finalgrade');
-    if ($uses_outcomes) {
-        $tablecolumns[] = 'outcome'; // no sorting based on outcomes column
-    }
-
-    $tableheaders = array('',
-                          get_string('fullname'),
-                          get_string('grade'),
-                          get_string('comment', 'lti'),
-                          get_string('lastmodified').' ('.get_string('submission', 'lti').')',
-                          get_string('lastmodified').' ('.get_string('grade').')',
-                          get_string('status'),
-                          get_string('finalgrade', 'grades'));
-    if ($uses_outcomes) {
-        $tableheaders[] = get_string('outcome', 'grades');
-    }
-
-    require_once($CFG->libdir.'/tablelib.php');
-    $table = new flexible_table('mod-lti-submissions');
-
-    $table->define_columns($tablecolumns);
-    $table->define_headers($tableheaders);
-    $table->define_baseurl($CFG->wwwroot.'/mod/lti/submissions.php?id='.$cm->id.'&amp;currentgroup='.$currentgroup);
-
-    $table->sortable(true, 'lastname');//sorted by lastname by default
-    $table->collapsible(true);
-    $table->initialbars(true);
-
-    $table->column_suppress('picture');
-    $table->column_suppress('fullname');
-
-    $table->column_class('picture', 'picture');
-    $table->column_class('fullname', 'fullname');
-    $table->column_class('grade', 'grade');
-    $table->column_class('submissioncomment', 'comment');
-    $table->column_class('timemodified', 'timemodified');
-    $table->column_class('timemarked', 'timemarked');
-    $table->column_class('status', 'status');
-    $table->column_class('finalgrade', 'finalgrade');
-    if ($uses_outcomes) {
-        $table->column_class('outcome', 'outcome');
-    }
-
-    $table->set_attribute('cellspacing', '0');
-    $table->set_attribute('id', 'attempts');
-    $table->set_attribute('class', 'submissions');
-    $table->set_attribute('width', '100%');
-
-    $table->no_sorting('finalgrade');
-    $table->no_sorting('outcome');
-
-    // Start working -- this is necessary as soon as the niceties are over
-    $table->setup();
-
-    if (empty($users)) {
-        echo $OUTPUT->heading(get_string('noviewusers', 'lti'));
-        echo '</div>';
-        return true;
-    }
-
-       /// Construct the SQL
-    list($where, $params) = $table->get_sql_where();
-    if ($where) {
-        $where .= ' AND ';
-    }
-
-    if ($sort = $table->get_sql_sort()) {
-        $sort = ' ORDER BY '.$sort;
-    }
-
-    $ufields = user_picture::fields('u');
-
-    $gradeitem = $DB->get_record('grade_items', array('courseid' => $cm->course, 'iteminstance' => $cm->instance));
-
-    $select = "SELECT $ufields,
-              g.rawgrade, g.feedback,
-              g.timemodified, g.timecreated ";
-
-    $sql = 'FROM {user} u'.
-            ' LEFT JOIN {grade_grades} g ON u.id = g.userid AND g.itemid = '.$gradeitem->id.
-            ' LEFT JOIN {grade_items} i ON g.itemid = i.id'.
-            ' AND i.iteminstance = '.$basiclti->id.
-            ' WHERE '.$where.'u.id IN ('.implode(',', $users).') ';
-
-    $ausers = $DB->get_records_sql($select.$sql.$sort, $params, $table->get_page_start(), $table->get_page_size());
-
-    $table->pagesize($perpage, count($users));
-
-    ///offset used to calculate index of student in that particular query, needed for the pop up to know who's next
-    $offset = $page * $perpage;
-    $strupdate = get_string('update');
-    $strgrade  = get_string('grade');
-    $grademenu = make_grades_menu($basiclti->grade);
-    if ($ausers !== false) {
-        $grading_info = grade_get_grades($course->id, 'mod', 'lti', $basiclti->id, array_keys($ausers));
-        $endposition = $offset + $perpage;
-        $currentposition = 0;
-        foreach ($ausers as $auser) {
-
-            if ($auser->timemodified > 0) {
-                $timemodified = '<div id="ts'.$auser->id.'">'.userdate($auser->timemodified).'</div>';
-            } else {
-                $timemodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
-            }
-            if ($auser->timecreated > 0) {
-                $timecreated = '<div id="ts'.$auser->id.'">'.userdate($auser->timecreated).'</div>';
-            } else {
-                $timecreated = '<div id="ts'.$auser->id.'">&nbsp;</div>';
-            }
-
-            if ($currentposition == $offset && $offset < $endposition) {
-                $final_grade = $grading_info->items[0]->grades[$auser->id];
-                $grademax = $grading_info->items[0]->grademax;
-                $final_grade->formatted_grade = round($final_grade->grade, 2) .' / ' . round($grademax, 2);
-                $locked_overridden = 'locked';
-                if ($final_grade->overridden) {
-                    $locked_overridden = 'overridden';
-                }
-
-                /// Calculate user status
-                $picture = $OUTPUT->user_picture($auser);
-
-                $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
-                $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
-                $status          = '<div id="st'.$auser->id.'">&nbsp;</div>';
-
-                if ($final_grade->locked or $final_grade->overridden) {
-                    $grade = '<div id="g'.$auser->id.'">'.$final_grade->formatted_grade . '</div>';
-                } else if ($quickgrade) {   // allow editing
-                    $attributes = array();
-                    $attributes['tabindex'] = $tabindex++;
-                    if ($auser->rawgrade != "") {
-                        $menu = html_writer::select(make_grades_menu($basiclti->grade), 'menu['.$auser->id.']', round($auser->rawgrade, 0), array(-1=>get_string('nograde')), $attributes);
-                    } else {
-                        $menu = html_writer::select(make_grades_menu($basiclti->grade), 'menu['.$auser->id.']', -1, array(-1=>get_string('nograde')), $attributes);
-                    }
-                    $grade = '<div id="g'.$auser->id.'">'.$menu.'</div>';
-                } else if ($final_grade->grade) {
-                    if ($auser->rawgrade != "") {
-                        $grade = '<div id="g'.$auser->id.'">'.$final_grade->formatted_grade.'</div>';
-                    } else {
-                        $grade = '<div id="g'.$auser->id.'">-1</div>';
-                    }
-
-                } else {
-                    $grade = '<div id="g'.$auser->id.'">No Grade</div>';
-                }
-
-                if ($final_grade->locked or $final_grade->overridden) {
-                    $comment = '<div id="com'.$auser->id.'">'.$final_grade->str_feedback.'</div>';
-                } else if ($quickgrade) {
-                    $comment = '<div id="com'.$auser->id.'">'
-                             . '<textarea tabindex="'.$tabindex++.'" name="submissioncomment['.$auser->id.']" id="submissioncomment'
-                             . $auser->id.'" rows="2" cols="20">'.($auser->feedback).'</textarea></div>';
-                } else {
-                    $comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($auser->feedback), 15).'</div>';
-                }
-
-                if (empty($auser->status)) { /// Confirm we have exclusively 0 or 1
-                    $auser->status = 0;
-                } else {
-                    $auser->status = 1;
-                }
-
-                $buttontext = ($auser->status == 1) ? $strupdate : $strgrade;
-
-                ///No more buttons, we use popups ;-).
-                $popup_url = '/mod/lti/submissions.php?id='.$cm->id
-                           . '&amp;userid='.$auser->id.'&amp;mode=single'.'&amp;filter='.$filter.'&amp;offset='.$offset++;
-
-                $button = $OUTPUT->action_link($popup_url, $buttontext);
-
-                $status  = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>';
-
-                $finalgrade = '<span id="finalgrade_'.$auser->id.'">'.$final_grade->str_grade.'</span>';
-
-                $outcomes = '';
-
-                if ($uses_outcomes) {
-
-                    foreach ($grading_info->outcomes as $n => $outcome) {
-                        $outcomes .= '<div class="outcome"><label>'.$outcome->name.'</label>';
-                        $options = make_grades_menu(-$outcome->scaleid);
-
-                        if ($outcome->grades[$auser->id]->locked or !$quickgrade) {
-                            $options[0] = get_string('nooutcome', 'grades');
-                            $outcomes .= ': <span id="outcome_'.$n.'_'.$auser->id.'">'.$options[$outcome->grades[$auser->id]->grade].'</span>';
-                        } else {
-                            $attributes = array();
-                            $attributes['tabindex'] = $tabindex++;
-                            $attributes['id'] = 'outcome_'.$n.'_'.$auser->id;
-                            $outcomes .= ' '.html_writer::select($options, 'outcome_'.$n.'['.$auser->id.']', $outcome->grades[$auser->id]->grade, array(0=>get_string('nooutcome', 'grades')), $attributes);
-                        }
-                        $outcomes .= '</div>';
-                    }
-                }
-
-                $userlink = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $auser->id . '&amp;course=' . $course->id . '">' . fullname($auser, has_capability('moodle/site:viewfullnames', $context)) . '</a>';
-                $row = array($picture, $userlink, $grade, $comment, $timemodified, $timecreated, $status, $finalgrade);
-                if ($uses_outcomes) {
-                    $row[] = $outcomes;
-                }
-
-                $table->add_data($row);
-            }
-            $currentposition++;
-        }
-    }
-
-    $table->print_html();  /// Print the whole table
-
-    /// Print quickgrade form around the table
-    if ($quickgrade && $table->started_output) {
-        $mailinfopref = false;
-        if (get_user_preferences('lti_mailinfo', 1)) {
-            $mailinfopref = true;
-        }
-        $emailnotification =  html_writer::checkbox('mailinfo', 1, $mailinfopref, get_string('enableemailnotification', 'lti'));
-
-        $emailnotification .= $OUTPUT->help_icon('enableemailnotification', 'lti');
-        echo html_writer::tag('div', $emailnotification, array('class'=>'emailnotification'));
-
-        $savefeedback = html_writer::empty_tag('input', array('type'=>'submit', 'name'=>'fastg', 'value'=>get_string('saveallfeedback', 'lti')));
-        echo html_writer::tag('div', $savefeedback, array('class'=>'fastgbutton'));
-
-        echo html_writer::end_tag('form');
-    } else if ($quickgrade) {
-        echo html_writer::end_tag('form');
-    }
-
-    echo '</div>';
-    /// End of fast grading form
-
-    /// Mini form for setting user preference
-
-    $formaction = new moodle_url('/mod/lti/submissions.php', array('id'=>$cm->id));
-    $mform = new MoodleQuickForm('optionspref', 'post', $formaction, '', array('class'=>'optionspref'));
-
-    $mform->addElement('hidden', 'updatepref');
-    $mform->setDefault('updatepref', 1);
-    $mform->addElement('header', 'qgprefs', get_string('optionalsettings', 'lti'));
-//        $mform->addElement('select', 'filter', get_string('show'),  $filters);
-
-    $mform->setDefault('filter', $filter);
-
-    $mform->addElement('text', 'perpage', get_string('pagesize', 'lti'), array('size'=>1));
-    $mform->setDefault('perpage', $perpage);
-
-    $mform->addElement('checkbox', 'quickgrade', get_string('quickgrade', 'lti'));
-    $mform->setDefault('quickgrade', $quickgrade);
-    $mform->addHelpButton('quickgrade', 'quickgrade', 'lti');
-
-    $mform->addElement('submit', 'savepreferences', get_string('savepreferences'));
-
-    $mform->display();
-
-    echo $OUTPUT->footer();
-}
-
 /**
  * Create grade item for given basiclti
  *
@@ -1008,3 +362,14 @@ function lti_grade_item_delete($basiclti) {
     return grade_update('mod/lti', $basiclti->course, 'mod', 'lti', $basiclti->id, 0, null, array('deleted'=>1));
 }
 
+function lti_extend_settings_navigation($settings, $parentnode) {
+    global $PAGE;
+    
+    $keys = $parentnode->get_children_key_list();
+    
+    $node = navigation_node::create('Submissions',
+        new moodle_url('/mod/lti/grade.php', array('id'=>$PAGE->cm->id)),
+        navigation_node::TYPE_SETTING, null, 'mod_lti_submissions');
+    
+    $parentnode->add_node($node, $keys[1]);
+}
\ No newline at end of file
index 60162b3..bfb55bc 100644 (file)
@@ -95,6 +95,8 @@ function lti_view($instance, $makeobject=false) {
         $typeconfig['sendname'] = $instance->instructorchoicesendname;
         $typeconfig['sendemailaddr'] = $instance->instructorchoicesendemailaddr;
         $typeconfig['customparameters'] = $instance->instructorcustomparameters;
+        $typeconfig['acceptgrades'] = $instance->instructorchoiceacceptgrades;
+        $typeconfig['allowroster'] = $instance->instructorchoiceallowroster;
     }
     
     //Default the organizationid if not specified
@@ -131,11 +133,16 @@ function lti_view($instance, $makeobject=false) {
     echo $content;
 }
 
-function lti_build_sourcedid($instanceid, $userid, $servicesalt){
+function lti_build_sourcedid($instanceid, $userid, $launchid = null, $servicesalt){
     $data = new stdClass();
         
     $data->instanceid = $instanceid;
     $data->userid = $userid;
+    if(!empty($launchid)){
+        $data->launchid = $launchid;
+    } else {
+        $data->launchid = mt_rand();
+    }
 
     $json = json_encode($data);
 
@@ -183,7 +190,7 @@ function lti_build_request($instance, $typeconfig, $course) {
     $placementsecret = $instance->servicesalt;
         
     if ( isset($placementsecret) ) {
-        $sourcedid = json_encode(lti_build_sourcedid($instance->id, $USER->id, $placementsecret));
+        $sourcedid = json_encode(lti_build_sourcedid($instance->id, $USER->id, null, $placementsecret));
     }
 
     if ( isset($placementsecret) &&
@@ -998,44 +1005,6 @@ function lti_post_launch_html($newparms, $endpoint, $debug=false) {
     return $r;
 }
 
-/**
- * Returns a link with info about the state of the basiclti submissions
- *
- * This is used by view_header to put this link at the top right of the page.
- * For teachers it gives the number of submitted assignments with a link
- * For students it gives the time of their submission.
- * This will be suitable for most assignment types.
- *
- * @global object
- * @global object
- * @param bool $allgroup print all groups info if user can access all groups, suitable for index.php
- * @return string
- */
-function lti_submittedlink($cm, $allgroups=false) {
-    global $CFG;
-
-    $submitted = '';
-    $urlbase = "{$CFG->wwwroot}/mod/lti/";
-
-    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-    if (has_capability('mod/lti:grade', $context)) {
-        if ($allgroups and has_capability('moodle/site:accessallgroups', $context)) {
-            $group = 0;
-        } else {
-            $group = groups_get_activity_group($cm);
-        }
-
-        $submitted = '<a href="'.$urlbase.'submissions.php?id='.$cm->id.'">'.
-                     get_string('viewsubmissions', 'lti').'</a>';
-    } else {
-        if (isloggedin()) {
-            // TODO Insert code for students if needed
-        }
-    }
-
-    return $submitted;
-}
-
 function lti_get_type($typeid){
     global $DB;
     
index 3dcb890..9792037 100644 (file)
@@ -20,7 +20,7 @@ switch($messagetype){
         lti_verify_sourcedid($ltiinstance, $parsed);
         lti_verify_message($ltiinstance, $rawbody);
         
-        $gradestatus = lti_update_grade($ltiinstance, $parsed->userid, $parsed->gradeval);
+        $gradestatus = lti_update_grade($ltiinstance, $parsed->userid, $parsed->launchid, $parsed->gradeval);
         
         $responsexml = lti_get_response_xml(
                 $gradestatus ? 'success' : 'error', 
index b3a6168..98e352a 100644 (file)
@@ -49,6 +49,7 @@ function lti_parse_grade_replace_message($xml){
     
     $parsed->instanceid = $resultjson->data->instanceid;
     $parsed->userid = $resultjson->data->userid;
+    $parsed->launchid = $resultjson->data->launchid;
     $parsed->sourcedidhash = $resultjson->hash;
     
     $parsed->messageid = lti_parse_message_id($xml);
@@ -63,6 +64,7 @@ function lti_parse_grade_read_message($xml){
     $parsed = new stdClass();
     $parsed->instanceid = $resultjson->data->instanceid;
     $parsed->userid = $resultjson->data->userid;
+    $parsed->launchid = $resultjson->data->launchid;
     $parsed->sourcedidhash = $resultjson->hash;
     
     $parsed->messageid = lti_parse_message_id($xml);
@@ -77,6 +79,7 @@ function lti_parse_grade_delete_message($xml){
     $parsed = new stdClass();
     $parsed->instanceid = $resultjson->data->instanceid;
     $parsed->userid = $resultjson->data->userid;
+    $parsed->launchid = $resultjson->data->launchid;
     $parsed->sourcedidhash = $resultjson->hash;
     
     $parsed->messageid = lti_parse_message_id($xml);
@@ -84,8 +87,8 @@ function lti_parse_grade_delete_message($xml){
     return $parsed;
 }
 
-function lti_update_grade($ltiinstance, $userid, $gradeval){
-    global $CFG;
+function lti_update_grade($ltiinstance, $userid, $launchid, $gradeval){
+    global $CFG, $DB;
     require_once($CFG->libdir . '/gradelib.php');
     
     $params = array();
@@ -97,6 +100,33 @@ function lti_update_grade($ltiinstance, $userid, $gradeval){
 
     $status = grade_update(LTI_SOURCE, $ltiinstance->course, LTI_ITEM_TYPE, LTI_ITEM_MODULE, $ltiinstance->id, 0, $grade, $params);    
 
+    $record = $DB->get_record('lti_submission', array('ltiid' => $ltiinstance->id, 'userid' => $userid, 'launchid' => $launchid), 'id');
+    if($record){
+        $id = $record->id;
+    } else {
+        $id = null;
+    }
+    
+    if(!empty($id)){
+        $DB->update_record('lti_submission', array(
+            'id' => $id,
+            'dateupdated' => time(),
+            'gradepercent' => $gradeval,
+            'state' => 2
+        ));
+    } else {
+        $DB->insert_record('lti_submission', array(
+            'ltiid' => $ltiinstance->id,
+            'userid' => $userid, 
+            'datesubmitted' => time(), 
+            'dateupdated' => time(),
+            'gradepercent' => $gradeval,
+            'originalgrade' => $gradeval,
+            'launchid' => $launchid,
+            'state' => 1
+        ));
+    }
+    
     return $status == GRADE_UPDATE_OK;
 }
 
@@ -156,7 +186,7 @@ function lti_verify_message($ltiinstance, $body, $headers = null){
 }
 
 function lti_verify_sourcedid($ltiinstance, $parsed){
-    $sourceid = lti_build_sourcedid($parsed->instanceid, $parsed->userid, $ltiinstance->servicesalt);
+    $sourceid = lti_build_sourcedid($parsed->instanceid, $parsed->userid, $parsed->launchid, $ltiinstance->servicesalt);
     
     if($sourceid->hash != $parsed->sourcedidhash){
         throw new Exception('SourcedId hash not valid');
diff --git a/mod/lti/submissions.js b/mod/lti/submissions.js
new file mode 100644 (file)
index 0000000..03188ee
--- /dev/null
@@ -0,0 +1,52 @@
+(function(){
+    var Y;
+    
+    M.mod_lti = M.mod_lti || {};
+    
+    M.mod_lti.submissions = {
+        init: function(yui3){
+            if(yui3){
+                Y = yui3;
+            }
+            
+            this.setupTable();
+            
+            
+        },
+        
+        setupTable: function(){
+            var lti_submissions_table = YAHOO.util.Dom.get('lti_submissions_table');
+    
+            var dataSource = new YAHOO.util.DataSource(lti_submissions_table);
+
+            var configuredColumns = [
+                { key: "user", label: "User", sortable:true },
+                { key: "date", label: "Submission Date", sortable:true, formatter: 'date' },
+                { key: "grade", 
+                  label: "Grade", 
+                  sortable:true, 
+                  formatter: function(cell, record, column, data){
+                      cell.innerHTML = parseFloat(data).toFixed(1) + '%';
+                  } 
+                }
+            ];
+
+            dataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
+            dataSource.responseSchema = {
+                fields: [
+                    { key: "user" },
+                    { key: "date", parser: "date" },
+                    { key: "grade", parser: "number" },
+                ]
+            };
+
+            new YAHOO.widget.DataTable("lti_submissions_table_container", configuredColumns, dataSource,
+                {
+                    sortedBy: {key:"date", dir:"desc"}
+                }
+            );
+            
+            Y.one('#lti_submissions_table_container').setStyle('display', '');
+        }
+    }
+})();
\ No newline at end of file
index 8b1f559..ea28f4e 100644 (file)
@@ -122,10 +122,6 @@ if($basiclti->showdescription && $basiclti->intro){
     echo $OUTPUT->box($basiclti->intro, 'generalbox description', 'intro');
 }
 
-if ($basiclti->instructorchoiceacceptgrades == 1) {
-    echo '<div class="reportlink">'.lti_submittedlink($cm).'</div>';
-}
-
 if ( $launchcontainer == LTI_LAUNCH_CONTAINER_WINDOW ) {
     echo "<script language=\"javascript\">//<![CDATA[\n";
     echo "window.open('launch.php?id=".$cm->id."','lti');";