diff --git a/amd/build/sorttable.min.js b/amd/build/sorttable.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..e1c931c17ccf0102e0257593db0b450fcb79de6b
--- /dev/null
+++ b/amd/build/sorttable.min.js
@@ -0,0 +1 @@
+define(["jquery"],function(a){return{makeSortable:function(b,c=[],d,e=0){var f;null===d&&(d=void 0);var g=a("#"+b+" tbody"),h=a("#"+b+" thead th"),i=h.length;h.each(function(){var b=h.index(this);-1==c.indexOf(b)&&-1==c.indexOf(b-i)&&a(this).append('<i class="icon fa fa-fw sortarrow"></i>')}),a("#"+b+" thead .sortarrow").each(function(){var b=a(this),c=b.closest("th"),d=h.index(c);c.css("cursor","pointer").css("user-select","none").click(function(){b.hasClass("sortarrow-active")?1==(f=-f)?b.removeClass("fa-caret-up").addClass("fa-caret-down"):b.removeClass("fa-caret-down").addClass("fa-caret-up"):(a("i.sortarrow-active").removeClass("sortarrow-active fa-caret-down fa-caret-up"),b.addClass("sortarrow-active fa-caret-down"),f=1);var c=1,h=Array.from(g.children("tr")),i=h.splice(-e,e);h.sort(function(b,c){var e=function(b){return a(b).find(".cell.c"+d+" [value]").attr("value")||a(b).find(".cell.c"+d).text()},g=e(b),h=e(c);return f*(""===g||""===h||isNaN(g)||isNaN(h)?g.toString().localeCompare(h):g-h)}).forEach(function(b){a(b).children("td").first().find(":not(:empty)").addBack(":not(:empty)").each(function(){/^[0-9]+$/.test(a(this).html())&&a(this).html(c)}),c++,g.append(b)}),i.forEach(function(a){g.append(a)})}),c.find("a").click(function(a){a.stopPropagation()})}).eq(d).click()}}});
\ No newline at end of file
diff --git a/amd/src/sorttable.js b/amd/src/sorttable.js
new file mode 100644
index 0000000000000000000000000000000000000000..f4d1b52f73ecf5b0c864027bc76910717f35ccc8
--- /dev/null
+++ b/amd/src/sorttable.js
@@ -0,0 +1,90 @@
+define(['jquery'], function($){
+
+    /**
+     * Makes an html table sortable by creating clickable column headers and arrows.
+     * @param tableid The id of the table to make sortable.
+     * @param nosortcols (optional) An array of column indexes to exclude.
+     *     Negative indexes can be specified to exclude columns counting from the last.
+     * @param defaultsortcol (optional) The index of the column to sort by default.
+     *     This index is computed after excluding columns. Negative indexes are allowed.
+     * @param nexcludedlines (optional) The number of lines to ignore at the end of the table.
+     */
+    function makeSortable(tableid, nosortcols=[], defaultsortcol, nexcludedlines=0){
+        var sortdirection;
+        if(defaultsortcol === null) {
+            defaultsortcol = undefined;
+        }
+        var table = $('#' + tableid + ' tbody');
+        var $ths = $('#' + tableid + ' thead th');
+        var nths = $ths.length;
+        $ths.each(function(){
+            // Create sorting arrows except for excluded columns.
+            var i = $ths.index(this);
+            if (nosortcols.indexOf(i) == -1 && nosortcols.indexOf(i - nths) == -1) {
+                $(this).append('<i class="icon fa fa-fw sortarrow"></i>');
+            }
+        });
+        // Setup sort arrows / headers.
+        $('#' + tableid + ' thead .sortarrow').each(function(){
+            var $arrow = $(this);
+            var $th = $arrow.closest('th');
+            var icol = $ths.index($th);
+            $th.css('cursor','pointer').css('user-select','none').click(function(){
+                if(!$arrow.hasClass('sortarrow-active')){
+                    // Change of sorting column: remove old sorting column arrow and setup the new one.
+                    $('i.sortarrow-active').removeClass('sortarrow-active fa-caret-down fa-caret-up');
+                    $arrow.addClass('sortarrow-active fa-caret-down');
+                    sortdirection = 1;
+                }
+                else {
+                    // Change sorting direction and arrow display.
+                    sortdirection = -sortdirection;
+                    if (sortdirection == 1) {
+                        $arrow.removeClass('fa-caret-up').addClass('fa-caret-down');
+                    }
+                    else {
+                        $arrow.removeClass('fa-caret-down').addClass('fa-caret-up');
+                    }
+                }
+                // Sort rows.
+                var num = 1;
+                var rows = Array.from(table.children('tr'));
+                var endrows = rows.splice(-nexcludedlines, nexcludedlines);
+                rows.sort(function(a, b){
+                        // Sort according to 'value' attributes or inner text.
+                        var getCellValue = function(tr){
+                            return $(tr).find('.cell.c' + icol + ' [value]').attr('value') || $(tr).find('.cell.c' + icol).text();
+                        };
+                        var v1 = getCellValue(a);
+                        var v2 = getCellValue(b);
+                        return sortdirection *
+                            (v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2));
+                })
+                .forEach(function(tr){
+                    // Renumber first column.
+                    var $firstcol = $(tr).children('td').first();
+                    $firstcol.find(':not(:empty)').addBack(':not(:empty)').each(function(){
+                        if(/^[0-9]+$/.test($(this).html())){
+                            $(this).html(num);
+                        }
+                    });
+                    num++;
+                    // Re-insert row inside table.
+                    table.append(tr);
+                });
+                // Re-insert excluded rows at the end.
+                endrows.forEach(function(tr){
+                    table.append(tr);
+                });
+            });
+            // Do not sort upon click on header link.
+            $th.find('a').click(function(e){
+                e.stopPropagation();
+            });
+        }).eq(defaultsortcol).click();
+    }
+
+    return {
+        makeSortable : makeSortable
+    };
+});
\ No newline at end of file
diff --git a/forms/gradesubmission.php b/forms/gradesubmission.php
index 60948c80b62a7033c567d8f42c16da9361c0e6ef..c701dad76a3998e87207521be96768134cc77d6b 100644
--- a/forms/gradesubmission.php
+++ b/forms/gradesubmission.php
@@ -147,7 +147,7 @@ if ($subinstance->dategraded == 0 || $subinstance->grader == $USER->id || $subin
             // Change grade info at parent window.
             $text = $submission->get_grade_core();
             $grader = fullname( $submission->get_grader( $USER->id ) );
-            $gradedon = userdate( $submission->get_instance()->dategraded );
+            $gradedon = $submission->get_gradedon_date_formatted();
             $jscript .= 'VPL.updatesublist(' . $submission->get_instance()->id . ',';
             $jscript .= '\'' . addslashes( $text ) . '\',';
             $jscript .= '\'' . addslashes( $grader ) . '\',';
diff --git a/index.php b/index.php
index 2fb5ee932468a8ea347f52a3703107263c5370b0..25dad4b5e46df83b652c7b60d4d167002f55008b 100644
--- a/index.php
+++ b/index.php
@@ -25,33 +25,21 @@
 
 require_once(dirname(__FILE__).'/../../config.php');
 require_once(dirname(__FILE__).'/locallib.php');
-require_once(dirname(__FILE__).'/list_util.class.php');
 require_once(dirname(__FILE__).'/vpl_submission.class.php');
 
 $id = required_param( 'id', PARAM_INT ); // Course id.
+$instanceselection = optional_param( 'selection', 'all', PARAM_RAW );
 
-
-$sort = vpl_get_set_session_var( 'sort', '' );
-$sortdir = vpl_get_set_session_var( 'sortdir', 'down' );
-$instanceselection = vpl_get_set_session_var( 'selection', 'all' );
+global $DB, $PAGE, $OUTPUT, $USER;
 
 // Check course existence.
 if (! $course = $DB->get_record( "course", array ( 'id' => $id ) )) {
     print_error( 'invalidcourseid', '', $id );
 }
 require_course_login( $course );
-// Load strings.
-$burl = vpl_rel_url( basename( __FILE__ ), 'id', $id );
-$strname = get_string( 'name' ) . ' ';
-$strname .= vpl_list_util::vpl_list_arrow( $burl, 'name', $instanceselection, $sort, $sortdir );
+
+
 $strvpls = get_string( 'modulenameplural', VPL );
-$strshortdescription = get_string( 'shortdescription', VPL ) . ' ';
-$strshortdescription .= vpl_list_util::vpl_list_arrow( $burl, 'shortdescription', $instanceselection, $sort, $sortdir );
-$strstartdate = get_string( 'startdate', VPL ) . ' ';
-$strstartdate .= vpl_list_util::vpl_list_arrow( $burl, 'startdate', $instanceselection, $sort, $sortdir );
-$strduedate = get_string( 'duedate', VPL ) . ' ';
-$strduedate .= vpl_list_util::vpl_list_arrow( $burl, 'duedate', $instanceselection, $sort, $sortdir );
-$strnopls = get_string( 'novpls', VPL );
 
 $PAGE->set_url( '/mod/vpl/index.php', array ( 'id' => $id ) );
 $PAGE->navbar->add( $strvpls );
@@ -65,11 +53,8 @@ $event = \mod_vpl\event\course_module_instance_list_viewed::create( $einfo );
 $event->trigger();
 
 // Print selection by instance state.
-
 $urlbase = new moodle_url( '/mod/vpl/index.php', array (
-        'id' => $id,
-        'sort' => $sort,
-        'sortdir' => $sortdir
+        'id' => $id
 ) );
 $urls = array ();
 $urlindex = array ();
@@ -92,9 +77,8 @@ foreach (array (
 }
 echo $OUTPUT->url_select( $urls, $urlindex [$instanceselection], array () );
 
-if (! $cms = get_coursemodules_in_course( VPL, $course->id, "m.shortdescription, m.startdate, m.duedate" )) {
-    vpl_redirect( vpl_abs_href( '/course/view.php', 'id', $course->id ),
-                  $strnopls);
+if (empty(get_coursemodules_in_course( VPL, $course->id, "m.shortdescription, m.startdate, m.duedate" ))) {
+    vpl_redirect( vpl_abs_href( '/course/view.php', 'id', $course->id ), get_string( 'novpls', VPL ) );
     die();
 }
 $ovpls = get_all_instances_in_course( VPL, $course );
@@ -178,23 +162,13 @@ foreach ($vpls as $vpl) {
 $grader = $grader && ! $nograde;
 $student = $student && ! $nograde;
 
-// The usort of old PHP versions don't call static class functions.
-if ($sort > '') {
-    $corder = new vpl_list_util();
-    $corder->set_order( $sort, $sortdir == 'down' );
-    usort( $vpls, array (
-            $corder,
-            'cpm'
-    ) );
-}
-
 // Generate table.
 $table = new html_table();
 $table->attributes ['class'] = 'generaltable mod_index';
 $table->head = array (
         '#',
-        $strname,
-        $strshortdescription
+        get_string( 'name' ),
+        get_string( 'shortdescription', VPL )
 );
 $table->align = array (
         'left',
@@ -202,11 +176,11 @@ $table->align = array (
         'left'
 );
 if ($startdate) {
-    $table->head [] = $strstartdate;
+    $table->head [] = get_string( 'startdate', VPL );
     $table->align [] = 'center';
 }
 if ($duedate) {
-    $table->head [] = $strduedate;
+    $table->head [] = get_string( 'duedate', VPL );
     $table->align [] = 'center';
 }
 if ($grader && ! $nograde) {
@@ -239,7 +213,7 @@ foreach ($vpls as $vpl) {
     if ($grader) {
         if ($vpl->has_capability( VPL_GRADE_CAPABILITY )
             && $vpl->get_grade() != 0 && ! $instance->example) {
-            $info = vpl_list_util::count_graded( $vpl );
+            $info = $vpl->count_graded();
             $totalsubs += $info ['submissions'];
             $totalgraded += $info ['graded'];
             $url = vpl_rel_url( 'views/submissionslist.php', 'id', $vpl->get_course_module()->id, 'selection', 'allsubmissions' );
@@ -298,23 +272,21 @@ foreach ($vpls as $vpl) {
     $table->data [] = $row;
 }
 if ($totalsubs > 0) {
-    $row = array ('', '', '');
-    if ($startdate) {
-        $row [] = '';
-    }
-    if ($duedate) {
-        $row [] = '';
-    }
-    end( $row );
-    $row [key( $row )] = get_string( 'total' );
+    $row = array_fill(0, count($table->head) - 2, '');
+    $row [1] = get_string( 'total' );
     $row [] = $totalsubs;
     $row [] = $totalgraded;
+    $table->data [] = array_fill(0, count($table->head), '');
     $table->data [] = $row;
+    $extrarows = 2;
+} else {
+    $extrarows = 0;
 }
+$table->id = 'vplindex';
+$PAGE->requires->js_call_amd('mod_vpl/sorttable', 'makeSortable', array('vplindex', array(0, 2), null, $extrarows));
 echo "<br />";
 echo html_writer::table( $table );
 $url = new moodle_url( '/mod/vpl/views/checkvpls.php', array ('id' => $id) );
-$string = get_string( 'checkall' );
-echo html_writer::link($url, $string, array('class' => 'btn btn-secondary'));
+echo html_writer::link($url, get_string( 'checkgroups', VPL ), array('class' => 'btn btn-secondary'));
 
 echo $OUTPUT->footer();
diff --git a/jscript/updatesublist.js b/jscript/updatesublist.js
index 4eeac82229ace30130cdcff16cb31576f483a9dc..8cb80eb10c40584c0fe70a5a34c5668859e60a40 100644
--- a/jscript/updatesublist.js
+++ b/jscript/updatesublist.js
@@ -70,10 +70,24 @@
             window.close();
         }
         var ssubid = "" + subid;
-        var divnext = opener.document.getElementById('n' + ssubid);
-        if (divnext) {
-            location.replace(url + divnext.innerHTML);
-        }else{
+        var divgrade = opener.document.getElementById('g' + ssubid);
+        while (divgrade.parentNode.nodeName !== 'TR' && divgrade.parentNode !== null) {
+            divgrade = divgrade.parentNode;
+        }
+        if (divgrade.parentNode === null) {
+            window.close();
+            return;
+        }
+        var nextrow = divgrade.parentNode.nextSibling;
+        if (nextrow === null) {
+            window.close();
+            return;
+        }
+        var rowhtml = nextrow.innerHTML;
+        var nextid = rowhtml.match(/user\/view\.php\?(.*?)id=([0-9]+)/)[2];
+        if (nextid) {
+            location.replace(url + nextid);
+        } else {
             window.close();
         }
     };
diff --git a/lang/en/vpl.php b/lang/en/vpl.php
index 06143b19ba2d4e32a0af0b88fd7576e0d4b958a3..2c551c31c01da139e86541c6bf5222792de8c56f 100644
--- a/lang/en/vpl.php
+++ b/lang/en/vpl.php
@@ -90,6 +90,7 @@ $string ['evaluate'] = 'Evaluate';
 $string ['evaluateonsubmission'] = 'Evaluate just on submission';
 $string ['evaluating'] = 'Evaluating';
 $string ['evaluation'] = 'Evaluation';
+$string ['evaluations'] = 'Automatic evaluations';
 $string ['examples'] = 'Examples';
 $string ['execution'] = 'Execution';
 $string ['executionfiles'] = 'Execution files';
@@ -169,6 +170,7 @@ $string ['maxfiles'] = 'Maximum number of files';
 $string ['maxfilesexceeded'] = 'Maximum number of files exceeded';
 $string ['maxfilesize'] = 'Maximum upload file size';
 $string ['maxfilesizeexceeded'] = 'Maximum file size exceeded';
+$string ['maxgradeobtained'] = 'Max grade obtained';
 $string ['maximumperiod'] = 'Maximum period {$a}';
 $string ['maxresourcelimits'] = 'Maximum execution resources limits';
 $string ['maxsimilarityoutput'] = 'Maximum output by similarity';
@@ -263,6 +265,7 @@ $string ['submission'] = 'Submission';
 $string ['submissionperiod'] = 'Submission period';
 $string ['submissionrestrictions'] = 'Submission restrictions';
 $string ['submissions'] = 'Submissions';
+$string ['submissionscharts'] = 'Submissions charts';
 $string ['submissionselection'] = 'Submission selection';
 $string ['submissionslist'] = 'Submissions list';
 $string ['submissionview'] = 'Submission view';
diff --git a/lib.php b/lib.php
index 6741f6071c6779ffa391b27f1b2bdee31d255faa..8d996ac4f6f294f4ec6b2e87169873782ece4211 100644
--- a/lib.php
+++ b/lib.php
@@ -26,7 +26,6 @@
 defined('MOODLE_INTERNAL') || die();
 
 require_once(dirname(__FILE__).'/locallib.php');
-require_once(dirname(__FILE__).'/list_util.class.php');
 require_once($CFG->dirroot.'/course/lib.php');
 
 /**
@@ -499,10 +498,11 @@ function mod_vpl_get_fontawesome_icon_map() {
             'mod_vpl:submissionslist' => 'fa-list-ul',
             'mod_vpl:loading' => 'fa-spinner fa-pulse',
             'mod_vpl:copy' => 'fa-copy',
-            'mod_vpl:submissions' => 'fa-bar-chart',
+            'mod_vpl:submissionscharts' => 'fa-bar-chart',
             'mod_vpl:gradercomments' => 'fa-check-square',
             'mod_vpl:downloadsubmissions' => 'fa-cloud-download',
             'mod_vpl:downloadallsubmissions' => 'fa-history',
+            'mod_vpl:group' => 'fa-group',
     ];
 }
 
diff --git a/list_util.class.php b/list_util.class.php
deleted file mode 100644
index 066b4fde429f412d468be8a17ed4dd54e5406184..0000000000000000000000000000000000000000
--- a/list_util.class.php
+++ /dev/null
@@ -1,135 +0,0 @@
-<?php
-// This file is part of VPL for Moodle - http://vpl.dis.ulpgc.es/
-//
-// VPL for Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// VPL for Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with VPL for Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * List utility class
- *
- * @package mod_vpl
- * @copyright 2012 Juan Carlos Rodríguez-del-Pino
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- * @author Juan Carlos Rodríguez-del-Pino <jcrodriguez@dis.ulpgc.es>
- */
-
-defined( 'MOODLE_INTERNAL' ) || die();
-class vpl_list_util {
-    static protected $fields; // Field to compare.
-    static protected $ascending; // Value to return when ascending or descending order.
-    // Compare two submission fields.
-    static public function cpm($avpl, $bvpl) {
-        $a = $avpl->get_instance();
-        $b = $bvpl->get_instance();
-        foreach (self::$fields as $field) {
-            $avalue = $a->$field;
-            $bvalue = $b->$field;
-            if ($avalue == $bvalue) {
-                continue;
-            } else if ($avalue < $bvalue) {
-                return self::$ascending;
-            } else {
-                return - self::$ascending;
-            }
-        }
-        return 0;
-    }
-
-    /**
-     * Check and set data to sort return comparation function $field field to compare $descending order
-     */
-    static public function set_order($field, $ascending = true) {
-        $sortfields = array (
-                'name' => array (
-                        'name'
-                ),
-                'shortdescription' => array (
-                        'shortdescription'
-                ),
-                'startdate' => array (
-                        'startdate',
-                        'duedate',
-                        'name'
-                ),
-                'duedate' => array (
-                        'duedate',
-                        'startdate',
-                        'name'
-                ),
-                'automaticgrading' => array (
-                        'automaticgrading',
-                        'duedate',
-                        'name'
-                )
-        );
-        if (isset( $sortfields [$field] )) {
-            self::$fields = $sortfields [$field];
-        } else { // Unknow field.
-            self::$fields = $sortfields ['duedate'];
-        }
-        if ($ascending) {
-            self::$ascending = - 1;
-        } else {
-            self::$ascending = 1;
-        }
-    }
-    static public function vpl_list_arrow($burl, $sort, $instanceselection, $selsort, $seldir) {
-        global $OUTPUT;
-        $newdir = 'down'; // Dir to go if clicked.
-        $url = vpl_url_add_param( $burl, 'sort', $sort );
-        $url = vpl_url_add_param( $url, 'selection', $instanceselection );
-        if ($sort == $selsort) {
-            $sortdir = $seldir;
-            if ($sortdir == 'up') {
-                $newdir = 'down';
-            } else if ($sortdir == 'down') {
-                $newdir = 'up';
-            } else { // Unknow sortdir.
-                $sortdir = 'down';
-            }
-            $url = vpl_url_add_param( $url, 'sortdir', $newdir );
-        } else {
-            $sortdir = 'move';
-        }
-        return '<a href="' . $url . '">' . ($OUTPUT->pix_icon( 't/' . $sortdir, get_string( $sortdir ) )) . '</a>';
-    }
-
-    // Count submissions graded.
-    static public function count_graded($vpl) {
-        $numsubs = 0;
-        $numgraded = 0;
-        $subs = $vpl->all_last_user_submission( 's.dategraded, s.userid' );
-        if ($vpl->is_group_activity()) { // Fixes group activity userid.
-            foreach ($subs as $sub) {
-                $group = $vpl->get_group_members($sub->groupid);
-                if ( count($group) ) {
-                    $user = reset($group);
-                    $sub->userid = $user->id;
-                }
-            }
-        }
-        $students = $vpl->get_students();
-        foreach ($subs as $sub) {
-            if (isset( $students [$sub->userid] )) {
-                $numsubs ++;
-                if ($sub->dategraded > 0) { // Is graded.
-                    $numgraded ++;
-                }
-            }
-        }
-        return array (
-                'submissions' => $numsubs,
-                'graded' => $numgraded
-        );
-    }
-}
diff --git a/views/submissionslist.php b/views/submissionslist.php
index 49e00043ee83baf95771a3171af458539a209558..3af88f370b514233b9e27fd2397cc36a71d79a27 100644
--- a/views/submissionslist.php
+++ b/views/submissionslist.php
@@ -24,138 +24,18 @@
  */
 
 require_once(dirname( __FILE__ ) . '/../../../config.php');
+
+global $CFG, $OUTPUT, $USER, $PAGE;
 require_once($CFG->dirroot.'/mod/vpl/locallib.php');
 require_once($CFG->dirroot.'/mod/vpl/vpl.class.php');
+require_once($CFG->dirroot.'/mod/vpl/vpl_submission.class.php');
 require_once($CFG->dirroot.'/mod/vpl/vpl_submission_CE.class.php');
 
-class vpl_submissionlist_order {
-    protected static $field; // Field to compare.
-    protected static $ascending; // Value to return when ascending or descending order
-    protected static $corder = null; // Funtion usort of old PHP versions don't call static class functions
-    // Compare two submission fields.
-    static public function cpm_userid($a, $b) {
-        if ($a->userinfo->id < $b->userinfo->id) {
-            return self::$ascending;
-        } else {
-            return - self::$ascending;
-        }
-    }
-    // Compare two userinfo fields.
-    static public function cpm_userinfo($a, $b) {
-        $field = self::$field;
-        $adata = $a->userinfo->$field;
-        $bdata = $b->userinfo->$field;
-        if ($adata == $bdata) {
-            return self::cpm_userid( $a, $b );
-        }
-        if (is_string( $adata ) && function_exists( 'core_collator::compare' )) {
-            return (core_collator::compare( $adata, $bdata )) * (self::$ascending);
-        }
-        if ($adata < $bdata) {
-            return self::$ascending;
-        } else {
-            return - self::$ascending;
-        }
-    }
-    // Compare two submission fields.
-    static public function cpm_submission($a, $b) {
-        $field = self::$field;
-        $submissiona = $a->submission;
-        $submissionb = $b->submission;
-        if ($submissiona == $submissionb) {
-            return self::cpm_userid( $a, $b );
-        }
-        if ($submissiona == null) {
-            return self::$ascending;
-        }
-        if ($submissionb == null) {
-            return - self::$ascending;
-        }
-        $adata = $submissiona->get_instance()->$field;
-        $bdata = $submissionb->get_instance()->$field;
-        if ($adata === null) {
-            return self::$ascending;
-        }
-        if ($bdata === null) {
-            return - self::$ascending;
-        }
-        if ($adata == $bdata) {
-            return self::cpm_userid( $a, $b );
-        } else if ($adata < $bdata) {
-            return self::$ascending;
-        } else {
-            return - self::$ascending;
-        }
-    }
-
-    /**
-     * Check and set data to sort return comparation function $field field to compare $descending order
-     *
-     * @return array with function name
-     */
-    static public function set_order($field, $ascending = true) {
-        if (self::$corder === null) {
-            self::$corder = new vpl_submissionlist_order();
-        }
-        $userinfofields = array (
-                'firstname' => 0,
-                'lastname' => 0
-        );
-        $submissionfields = array (
-                'datesubmitted' => 0,
-                'gradesortable' => 0,
-                'grader' => 0,
-                'dategraded' => 0,
-                'nsubmissions' => 0
-        );
-        self::$field = $field;
-        if ($ascending) {
-            self::$ascending = - 1;
-        } else {
-            self::$ascending = 1;
-        }
-        // Funtion usort of old PHP versions don't call static class functions.
-        if (isset( $userinfofields [$field] )) {
-            return array (
-                    self::$corder,
-                    'cpm_userinfo'
-            );
-        } else if (isset( $submissionfields [$field] )) {
-            return array (
-                    self::$corder,
-                    'cpm_submission'
-            );
-        } else {
-            self::$field = 'firstname';
-            return array (
-                    self::$corder,
-                    'cpm_userinfo'
-            );
-        }
-    }
-}
-function vpl_submissionlist_arrow($burl, $sort, $selsort, $seldir) {
-    global $OUTPUT;
-    $newdir = 'down';
-    $url = vpl_url_add_param( $burl, 'sort', $sort );
-    if ($sort == $selsort) {
-        $sortdir = $seldir;
-        if ($sortdir == 'up') {
-            $newdir = 'down';
-        } else if ($sortdir == 'down') {
-            $newdir = 'up';
-        }
-    } else {
-        $sortdir = 'move';
-    }
-    $url = vpl_url_add_param( $url, 'sortdir', $newdir );
-    return ' <a href="' . $url . '">' . ($OUTPUT->pix_icon( 't/' . $sortdir, get_string( $sortdir ) )) . '</a>';
-}
 function vpl_get_listmenu($showgrades, $id) {
     $menu = new action_menu();
     $url = new moodle_url( '/mod/vpl/views/activityworkinggraph.php', array (
             'id' => $id) );
-    $menu->add(vpl_get_action_link('submissions', $url));
+    $menu->add(vpl_get_action_link('submissionscharts', $url));
     if ($showgrades) {
         $url = new moodle_url( '/mod/vpl/views/submissionslist.php', array (
                 'id' => $id) );
@@ -193,25 +73,18 @@ require_login();
 $id = required_param( 'id', PARAM_INT );
 $group = optional_param( 'group', - 1, PARAM_INT );
 $showgrades = optional_param( 'showgrades', 0, PARAM_INT );
-$sort = vpl_get_set_session_var( 'subsort', 'lastname', 'sort' );
-$sortdir = vpl_get_set_session_var( 'subsortdir', 'move', 'sortdir' );
 $subselection = vpl_get_set_session_var( 'subselection', 'allsubmissions', 'selection' );
 $vpl = new mod_vpl( $id );
 $vpl->prepare_page( 'views/submissionslist.php', array (
         'id' => $id
 ) );
 
-$course = $vpl->get_course();
 $cm = $vpl->get_course_module();
-$contextmodule = $vpl->get_context();
 $vpl->require_capability( VPL_GRADE_CAPABILITY );
 \mod_vpl\event\vpl_all_submissions_viewed::log( $vpl );
 
-// Print header.
-$vpl->print_header( get_string( 'submissionslist', VPL ) );
-$vpl->print_view_tabs( basename( __FILE__ ) );
-@ob_flush();
-flush();
+// Unblock user session.
+session_write_close();
 
 // Find out current groups mode.
 $groupmode = groups_get_activity_groupmode( $cm );
@@ -220,7 +93,6 @@ if (! $groupmode) {
 }
 
 // Get graders.
-$graders = $vpl->get_graders();
 $gradeable = $vpl->get_grade() != 0;
 
 // Get students.
@@ -229,85 +101,18 @@ if (! $currentgroup) {
     $currentgroup = '';
 }
 if ($vpl->is_group_activity()) {
-    $idfiels = 'groupid';
     $list = groups_get_all_groups($vpl->get_course()->id, 0, $cm->groupingid);
 } else {
     $list = $vpl->get_students( $currentgroup );
-    $idfiels = 'userid';
 }
 $submissions = $vpl->all_last_user_submission();
 $submissionsnumber = $vpl->get_submissions_number();
+$maxgrades = $vpl->get_max_grades();
 
-// Get all information.
-$alldata = array ();
-foreach ($list as $uginfo) {
-    $submission = null;
-    if (! isset( $submissions [$uginfo->id] )) {
-        if ($subselection != 'all') {
-            continue;
-        }
-    } else {
-        $subinstance = $submissions [$uginfo->id];
-        $submission = new mod_vpl_submission_CE( $vpl, $subinstance );
-        $subid = $subinstance->id;
-        $subinstance->gradesortable = null;
-        if ($subinstance->dategraded > 0) {
-            if ($subselection == 'notgraded') {
-                continue;
-            }
-            if ($subselection == 'gradedbyuser' && $subinstance->grader != $USER->id) {
-                continue;
-            }
-            // TODO REUSE showing.
-            $subinstance->gradesortable = $subinstance->grade;
-        } else {
-            $subinstance->grade = null;
-            if ($subselection == 'graded' || $subselection == 'gradedbyuser') {
-                continue;
-            }
-            // TODO REUSE showing.
-            $result = $submission->getCE();
-            if ($result ['executed'] !== 0) {
-                $prograde = $submission->proposedGrade( $result ['execution'] );
-                if ($prograde > '') {
-                    $subinstance->gradesortable = $prograde;
-                }
-            }
-        }
-        // I know that subinstance isn't the correct place to put nsubmissions but is the easy.
-        if (isset( $submissionsnumber [$uginfo->id] )) {
-            $subinstance->nsubmissions = $submissionsnumber [$uginfo->id]->submissions;
-        } else {
-            $subinstance->nsubmissions = ' ';
-        }
-    }
-    $data = new stdClass();
-    $data->userinfo = $uginfo;
-    $data->submission = $submission;
-    // When group activity => add lastname to groupname for order porpouse.
-    if ($vpl->is_group_activity()) {
-        $data->userinfo->firstname = '';
-        $data->userinfo->lastname = $uginfo->name;
-    }
-    $alldata [] = $data;
-}
-$groupsurl = vpl_mod_href( 'views/submissionslist.php', 'id', $id, 'sort', $sort, 'sortdir', $sortdir, 'selection', $subselection );
-// Unblock user session.
-session_write_close();
+$groupsurl = vpl_mod_href( 'views/submissionslist.php', 'id', $id, 'selection', $subselection );
 
-$baseurl = vpl_mod_href( 'views/submissionslist.php', 'id', $id, 'group', $group );
 
-$firstname = get_string( 'firstname' ) . vpl_submissionlist_arrow( $baseurl, 'firstname', $sort, $sortdir );
-$lastname = get_string( 'lastname' ) . vpl_submissionlist_arrow( $baseurl, 'lastname', $sort, $sortdir );
-if ($CFG->fullnamedisplay == 'lastname firstname') { // For better view (dlnsk).
-    $namesortselect = $lastname . ' / ' . $firstname;
-} else {
-    $namesortselect = $firstname . ' / ' . $lastname;
-}
-if ($vpl->is_group_activity()) {
-    $namesortselect = get_string( 'group' ) . vpl_submissionlist_arrow( $baseurl, 'lastname', $sort, $sortdir );
-}
-$options = array (
+$popupoptions = array (
         'height' => 550,
         'width' => 780,
         'directories' => 0,
@@ -318,106 +123,120 @@ $options = array (
         'toolbar' => 0
 );
 // Load strings.
-$strsubtime = get_string( 'submittedon', VPL ) . vpl_submissionlist_arrow( $baseurl, 'datesubmitted', $sort, $sortdir );
-$strgrade = get_string( 'grade' ) . vpl_submissionlist_arrow( $baseurl, 'gradesortable', $sort, $sortdir );
-$strgrader = get_string( 'grader', VPL ) . vpl_submissionlist_arrow( $baseurl, 'grader', $sort, $sortdir );
-$strgradedon = get_string( 'gradedon', VPL ) . vpl_submissionlist_arrow( $baseurl, 'dategraded', $sort, $sortdir );
+$firstname = get_string( 'firstname' );
+$lastname = get_string( 'lastname' );
+if ($CFG->fullnamedisplay == 'lastname firstname') { // For better view (dlnsk).
+    $namehead = $lastname . ' / ' . $firstname;
+} else {
+    $namehead = $firstname . ' / ' . $lastname;
+}
+if ($vpl->is_group_activity()) {
+    $strname = get_string( 'group' );
+} else {
+    $strname = $namehead;
+}
+$strsubtime = get_string( 'submittedon', VPL );
+$strgrade = get_string( 'grade' );
+if (!$showgrades) {
+    $hrefgradedetails = new moodle_url( '/mod/vpl/views/submissionslist.php', array ('id' => $id, 'showgrades' => 1) );
+    $linkgradedetails = $OUTPUT->action_link( $hrefgradedetails, '', null,
+            array( 'title' => get_string( 'gradercomments', VPL ) ),
+            new pix_icon('gradercomments', '', 'mod_vpl') );
+    $strgrade .= ' ' . $linkgradedetails;
+}
+$strgrader = get_string( 'grader', VPL );
+$strgradedon = get_string( 'gradedon', VPL );
+$strmaxgrade = get_string( 'maxgradeobtained', VPL );
 $strcomments = get_string( 'gradercomments', VPL );
 $hrefnsub = vpl_mod_href( 'views/activityworkinggraph.php', 'id', $id );
-$action = new popup_action( 'click', $hrefnsub, 'activityworkinggraph' . $id, $options );
-$linkworkinggraph = $OUTPUT->action_link( $hrefnsub, get_string( 'submissions', VPL ), $action );
-$strsubmisions = $linkworkinggraph . vpl_submissionlist_arrow( $baseurl, 'nsubmissions', $sort, $sortdir );
+$action = new popup_action( 'click', $hrefnsub, 'activityworkinggraph' . $id, $popupoptions );
+$linkworkinggraph = $OUTPUT->action_link( $hrefnsub, '', $action,
+        array ( 'title' => get_string( 'submissionscharts' , VPL ) ),
+        new pix_icon('submissionscharts', '', 'mod_vpl') );
+$strsubmissions = get_string( 'submissions', VPL ) . ' ' . $linkworkinggraph;
+$strnevaluations = get_string( 'evaluations', VPL );
 
 $table = new html_table();
+
+$table->head = array(
+        '',
+        $strname
+);
+
 if ($showgrades) {
-    $table->head = array (
-            '',
-            '',
-            $namesortselect,
+    $table->head = array_merge($table->head, array (
             $strgrade,
             $strcomments,
-            $OUTPUT->render(vpl_get_listmenu($showgrades, $id))
-    );
-    $table->aling = array (
-            'right',
-            'left',
-            'left',
-            'right',
-            'left'
-    );
-    $table->size = array (
-            '3em'
-    );
+            $strgrader,
+            $strgradedon
+    ));
 } else if ($gradeable) {
-    $table->head = array (
-            '',
-            '',
-            $namesortselect,
+    $table->head = array_merge($table->head, array (
             $strsubtime,
-            $strsubmisions,
+            $strsubmissions,
+            $strnevaluations,
             $strgrade,
-            $strgrader,
-            $strgradedon,
-            $OUTPUT->render(vpl_get_listmenu($showgrades, $id))
-    );
-    $table->size = array (
-            '3em',
-            '',
-            '',
-            '',
-            '3em'
-    );
-    $table->aling = array (
-            'right',
-            'left',
-            'left',
-            'right',
-            'right',
-            'right',
-            'right',
-            'left'
-    );
+            $strmaxgrade
+    ));
 } else {
-    $table->head = array (
-            '',
-            '',
-            $namesortselect,
+    $table->head = array_merge($table->head, array (
             $strsubtime,
-            $strsubmisions,
-            $OUTPUT->render(vpl_get_listmenu($showgrades, $id))
-    );
-    $table->size = array (
-            '3em',
-            '',
-            '',
-            '',
-            '3em'
-    );
-    $table->aling = array (
-            'right',
-            'left',
-            'left',
-            'right',
-            'right'
-    );
+            $strsubmissions
+    ));
 }
 
-// Sort by sort field.
-usort( $alldata, vpl_submissionlist_order::set_order( $sort, $sortdir != 'up' ) );
-$showphoto = count( $alldata ) < 100;
+$table->head[] = $OUTPUT->render(vpl_get_listmenu($showgrades, $id));
+
+$table->id = 'submissionstable';
+$PAGE->requires->js_call_amd('mod_vpl/sorttable', 'makeSortable', array('submissionstable', array(0, -1), 0));
+
 $usernumber = 0;
 $ngrades = array (); // Number of revisions made by teacher.
-$nextids = array (); // Information to get next user in list.
-$lastid = 0; // Last id for next.
+
 $userslists = array(
         'notexecuted' => array(),
         'notgraded' => array(),
         'all' => array()
 );
-foreach ($alldata as $data) {
+
+// Get all information.
+foreach ($list as $uginfo) {
+    $submission = null;
+    $nsubmissions = null;
+    $maxgradevalue = null;
+    if (! isset( $submissions [$uginfo->id] )) {
+        if ($subselection != 'all') {
+            continue;
+        }
+    } else {
+        $subinstance = $submissions [$uginfo->id];
+        $submission = new mod_vpl_submission_CE( $vpl, $subinstance );
+        $subid = $subinstance->id;
+        if ($subinstance->dategraded > 0) {
+            if ($subselection == 'notgraded') {
+                continue;
+            }
+            if ($subselection == 'gradedbyuser' && $subinstance->grader != $USER->id) {
+                continue;
+            }
+        } else {
+            $subinstance->grade = null;
+            if ($subselection == 'graded' || $subselection == 'gradedbyuser') {
+                continue;
+            }
+        }
+        if (isset( $submissionsnumber [$uginfo->id] )) {
+            $nsubmissions = $submissionsnumber [$uginfo->id]->submissions;
+        }
+
+        if (isset( $maxgrades [$uginfo->id] )) {
+            $maxgradevalue = $maxgrades [$uginfo->id]->maxgrade;
+        }
+    }
     $actions = new action_menu();
+    // When group activity => add lastname to groupname for order porpouse.
     if ($vpl->is_group_activity()) {
-        $gr = $data->userinfo;
+        $gr = $uginfo;
         $users = $vpl->get_group_members($gr->id);
         if ( count($users) == 0 ) {
             continue;
@@ -426,76 +245,61 @@ foreach ($alldata as $data) {
         $user->firstname = '';
         $user->lastname = $gr->name;
     } else {
-        $user = $data->userinfo;
+        $user = $uginfo;
     }
     $gradecomments = '';
     $linkparms = array('id' => $id, 'userid' => $user->id);
-    if ($data->submission == null) {
-        $text = get_string( 'nosubmission', VPL );
-        $hrefview = vpl_mod_href( 'forms/submissionview.php', 'id', $id, 'userid', $user->id, 'inpopup', 1 );
-        // TODO clean comment.
-        $action = new popup_action( 'click', $hrefview, 'viewsub' . $user->id, $options );
-        $subtime = $OUTPUT->action_link( $hrefview, $text, $action );
-        $link = new moodle_url('/mod/vpl/forms/submissionview.php', $linkparms);
-        $actions->add(vpl_get_action_link('submissionview', $link));
+    $viewlink = new moodle_url('/mod/vpl/forms/submissionview.php', $linkparms);
+    $actions->add(vpl_get_action_link('submissionview', $viewlink));
+    if ($submission == null) {
+        $subtime = $OUTPUT->action_link( $viewlink, get_string( 'nosubmission', VPL ) );
         $prev = '';
+        $evals = '';
         $grade = '';
         $grader = '';
         $gradedon = '';
+        $maxgrade = '';
     } else {
-        $submission = $data->submission;
-        $subinstance = $submission->get_instance();
-        $hrefview = vpl_mod_href( 'forms/submissionview.php', 'id', $id, 'userid', $user->id, 'inpopup', 1 );
-        $hrefprev = vpl_mod_href( 'views/previoussubmissionslist.php', 'id', $id, 'userid', $user->id, 'inpopup', 1 );
-        $hrefgrade = vpl_mod_href( 'forms/gradesubmission.php', 'id', $id, 'userid', $user->id, 'inpopup', 1 );
-        // TODO clean comment.
-        $link = new moodle_url('/mod/vpl/forms/submissionview.php', $linkparms);
-        $actions->add(vpl_get_action_link('submissionview', $link));
-        $subtime = $OUTPUT->action_link( $hrefview, userdate( $subinstance->datesubmitted ) );
-        if ($subinstance->nsubmissions > 0) {
-            $prev = $OUTPUT->action_link( $hrefprev, $subinstance->nsubmissions );
-            $link = new moodle_url('/mod/vpl/views/previoussubmissionslist.php', $linkparms);
-            $actions->add(vpl_get_action_link('previoussubmissionslist', $link));
+        $subtime = $OUTPUT->action_link( $viewlink, userdate( $subinstance->datesubmitted), null,
+                array(
+                        'title' => get_string('submissionview', VPL),
+                        'value' => $subinstance->datesubmitted
+                ) );
+        if ($nsubmissions !== null) {
+            $prevlink = new moodle_url('/mod/vpl/views/previoussubmissionslist.php', $linkparms);
+            $prev = $OUTPUT->action_link( $prevlink, $nsubmissions, null,
+                    array(
+                            'title' => get_string('previoussubmissionslist', VPL)
+                    ) );
+            $actions->add(vpl_get_action_link('previoussubmissionslist', $prevlink));
         } else {
             $prev = '';
         }
+        $evals = $subinstance->nevaluations;
         $subid = $subinstance->id;
         $userslists['all'][] = $user->id;
+        $gradevalue = $subinstance->grade;
+        $result = $submission->getCE();
+        if ($result ['executed'] !== 0) {
+            $prograde = $submission->proposedGrade( $result ['execution'] );
+        } else {
+            $userslists['notexecuted'][] = $user->id;
+            $prograde = '';
+        }
         if ($subinstance->dategraded > 0) {
-            $text = $submission->get_grade_core();
+            $gradetext = $submission->get_grade_core();
             // Add proposed grade diff.
-            $result = $submission->getCE();
-            if ($result ['executed'] !== 0) {
-                $prograde = $submission->proposedGrade( $result ['execution'] );
-                if ($prograde > '' && $prograde != $subinstance->grade) {
-                    $text .= ' (' . $prograde . ')';
-                }
-            }
-            $text = '<div id="g' . $subid . '">' . $text . '</div>';
-            if ($subinstance->grader == $USER->id) {
-                $action = new popup_action( 'click', $hrefgrade, 'gradesub' . $user->id, $options );
-                $grade = $OUTPUT->action_link( $hrefgrade, $text, $action );
-                $link = new moodle_url('/mod/vpl/forms/gradesubmission.php', $linkparms);
-                $actions->add( vpl_get_action_link('grade', $link, 'moodle') );
-                // Add new next user.
-                if ($lastid) {
-                    $nextids [$lastid] = $user->id;
-                }
-                $lastid = $subid; // Save submission id as next index.
-            } else {
-                $grade = $text;
+            if ($prograde > '' && $prograde != $subinstance->grade) {
+                $gradetext .= ' (' . $prograde . ')';
             }
-
             $graderid = $subinstance->grader;
-            $graderuser = $submission->get_grader( $graderid );
             // Count evaluator marks.
             if (isset( $ngrades [$graderid] )) {
                 $ngrades [$graderid] ++;
             } else {
                 $ngrades [$graderid] = 1;
             }
-            $grader = fullname( $graderuser );
-            $gradedon = userdate( $subinstance->dategraded );
+            $grader = fullname( mod_vpl_submission::get_grader( $graderid ) );
             if ($showgrades) {
                 $feedback = $submission->get_grade_comments();
                 if ($feedback) {
@@ -504,90 +308,83 @@ foreach ($alldata as $data) {
             }
         } else {
             $userslists['notgraded'][] = $user->id;
-            $result = $submission->getCE();
-            $text = '';
-            if ($result ['executed'] !== 0) {
-                $prograde = $submission->proposedGrade( $result ['execution'] );
-                if ($prograde > '') {
-                    $text = get_string( 'proposedgrade', VPL, $submission->get_grade_core( $prograde ) );
-                }
+            if ($prograde > '') {
+                $gradetext = get_string( 'proposedgrade', VPL, $submission->get_grade_core( $prograde ) );
+                $gradevalue = $prograde;
             } else {
-                $userslists['notexecuted'][] = $user->id;
+                $gradetext = get_string( 'nograde' );
             }
-            if ($text == '') {
-                $text = get_string( 'nograde' );
-            }
-            $action = new popup_action( 'click', $hrefgrade, 'gradesub' . $subinstance->userid, $options );
-            $text = '<div id="g' . $subid . '">' . $text . '</div>';
-            $grade = $OUTPUT->action_link( $hrefgrade, $text, $action );
-            $grader = '&nbsp;';
-            $gradedon = '&nbsp;';
-            $link = new moodle_url('/mod/vpl/forms/gradesubmission.php', $linkparms);
-            $actions->add(vpl_get_action_link('grade', $link, 'moodle'));
-            // Add new next user.
-            if ($lastid) {
-                $nextids [$lastid] = $user->id;
-            }
-            $lastid = $subid; // Save submission id as next index.
+            $grader = '';
+        }
+
+        $gradetext = '<div id="g' . $subid . '" class="gd' . $subid . '" value="'.$gradevalue.'">' . $gradetext . '</div>';
+        if ($subinstance->grader == $USER->id || !($subinstance->dategraded > 0)) {
+            $hrefgrade = vpl_mod_href( 'forms/gradesubmission.php', 'id', $id, 'userid', $user->id, 'inpopup', 1 );
+            $action = new popup_action( 'click', $hrefgrade, 'gradesub' . $user->id, $popupoptions );
+            $grade = $OUTPUT->action_link( $hrefgrade, $gradetext, $action,
+                    array(
+                            'title' => get_string('grade')
+                    ) );
+        } else {
+            $grade = $gradetext;
+        }
+
+        if ($maxgradevalue !== null) {
+            $maxgradetext = $vpl->format_grade($maxgradevalue);
+            $maxgrade = '<span value="'.$maxgradevalue.'">'.$maxgradetext.'</span>';
+        } else {
+            $maxgrade = '';
         }
+
+        $link = new moodle_url('/mod/vpl/forms/gradesubmission.php', $linkparms);
+        $actions->add(vpl_get_action_link('grade', $link, 'moodle'));
         // Add div id to submission info.
-        $grader = '<div id="m' . $subid . '">' . $grader . '</div>';
-        $gradedon = '<div id="o' . $subid . '">' . $gradedon . '</div>';
+        $grader = '<div id="m' . $subid . '" class="gd' . $subid . '">' . $grader . '</div>';
+        $gradedon = '<div id="o' . $subid . '" class="gd' . $subid . '">'.
+                        $submission->get_gradedon_date_formatted().
+                    '</div>';
     }
-    $url = vpl_mod_href( 'forms/edit.php', 'id', $id, 'userid', $user->id, 'privatecopy', 1 );
-    $options = array (
-            'height' => 550,
-            'width' => 780,
-            'directories' => 0,
-            'location' => 0,
-            'menubar' => 0,
-            'personalbar' => 0,
-            'status' => 0,
-            'toolbar' => 0
-    );
-    $action = new popup_action( 'click', $url, 'privatecopyl' . $id, $options );
+    $copylink = new moodle_url('/mod/vpl/forms/edit.php', array('id' => $id, 'userid' => $user->id, 'privatecopy' => 1));
+    $action = new popup_action( 'click', $copylink, 'privatecopyl' . $id, $popupoptions );
     $usernumber ++;
-    $usernumberlink = $OUTPUT->action_link( $url, $usernumber, $action);
-    $link = new moodle_url('/mod/vpl/forms/edit.php', array('id' => $id, 'userid' => $user->id, 'privatecopy' => 1));
-    $actions->add(vpl_get_action_link('copy', $link));
+    $usernumberlink = $OUTPUT->action_link( $copylink, $usernumber, $action,
+            array(
+                    'title' => get_string('copy', VPL)
+            ) );
+    $actions->add(vpl_get_action_link('copy', $copylink));
+
+    $submissiondata = array (
+            $usernumberlink,
+            '<span value="'.$user->lastname.'">' . $vpl->user_fullname_picture($user, false) . '</span>',
+    );
+
     if ($showgrades) {
-        $table->data [] = array (
-                $usernumberlink,
-                $showphoto ? $vpl->user_picture( $user ) : '',
-                $vpl->fullname( $user, !$showphoto),
+        $submissiondata = array_merge($submissiondata, array (
                 $grade,
                 $gradecomments,
-                $OUTPUT->render($actions)
-        );
+                $grader,
+                $gradedon
+        ));
     } else if ($gradeable) {
-        $table->data [] = array (
-                $usernumberlink,
-                $showphoto ? $vpl->user_picture( $user) : '',
-                $vpl->fullname( $user, !$showphoto),
+        $submissiondata = array_merge($submissiondata, array (
                 $subtime,
                 $prev,
+                $evals,
                 $grade,
-                $grader,
-                $gradedon,
-                $OUTPUT->render($actions)
-        );
+                $maxgrade
+        ));
     } else {
-        $table->data [] = array (
-                $usernumberlink,
-                $showphoto ? $vpl->user_picture( $user) : '',
-                $vpl->fullname( $user, !$showphoto),
+        $submissiondata = array_merge($submissiondata, array (
                 $subtime,
-                $prev,
-                $OUTPUT->render($actions)
-        );
+                $prev
+        ));
     }
+
+    $table->data [] = array_merge($submissiondata, array (
+            $OUTPUT->render($actions)
+    ));
 }
 if (count( $ngrades )) {
-    if ($CFG->fullnamedisplay == 'lastname firstname') { // For better view (dlnsk).
-        $namehead = get_string( 'lastname' ) . ' / ' . get_string( 'firstname' );
-    } else {
-        $namehead = get_string( 'firstname' ) . ' / ' . get_string( 'lastname' );
-    }
     $tablegraders = new html_table();
     $tablegraders->head = array (
             '#',
@@ -611,23 +408,30 @@ if (count( $ngrades )) {
         $grader = mod_vpl_submission::get_grader( $graderid );
         $picture = '';
         if ($graderid > 0) { // No automatic grading.
-            $picture = $OUTPUT->user_picture( $grader, array (
-                    'popup' => true
-            ) );
+            $picture = $OUTPUT->user_picture( $grader );
         }
         $tablegraders->data [] = array (
                 $gradernumber,
                 $picture . ' ' . fullname( $grader ),
-                sprintf( '%d/%d  (%5.2f%%)', $marks, $usernumber, ( float ) 100.0 * $marks / $usernumber )
+                sprintf( '%d/%d  (%.2f%%)', $marks, $usernumber, ( float ) 100.0 * $marks / $usernumber )
         );
     }
 }
+
+
+
+// Print header.
+$vpl->print_header( get_string( 'submissionslist', VPL ) );
+$vpl->print_view_tabs( basename( __FILE__ ) );
+@ob_flush();
+flush();
+
 // Menu for groups.
 if ($groupmode) {
     groups_print_activity_menu( $cm, $groupsurl );
 }
 // Print user selection by submission state.
-$urlbase = $CFG->wwwroot . "/mod/vpl/views/submissionslist.php?id=$id&sort=$sort&group=$group&selection=";
+$urlbase = $CFG->wwwroot . "/mod/vpl/views/submissionslist.php?id=$id&group=$group&selection=";
 $urlindex = vpl_select_index( $urlbase, array (
         'all',
         'allsubmissions',
@@ -643,7 +447,7 @@ $urls = array_merge( array (
         'graded',
         'gradedbyuser'
 ) ) );
-$urlsel = new url_select( $urls, $urlindex [$subselection] );
+$urlsel = new url_select( $urls, $urlindex [$subselection], null );
 $urlsel->set_label( get_string( 'submissionselection', VPL ) );
 echo $OUTPUT->render( $urlsel );
 
@@ -677,14 +481,4 @@ if (count( $ngrades ) > 0) {
     echo '<br />';
     echo html_writer::table( $tablegraders );
 }
-
-// Generate next info as <div id="submissionid">nextuser</div>.
-if (count( $nextids )) {
-    // Hide info.
-    echo '<div style="display:none;">';
-    foreach ($nextids as $subid => $nextuser) {
-        echo '<div id="n' . $subid . '">' . $nextuser . '</div>';
-    }
-    echo '</div>';
-}
-$vpl->print_footer();
+$vpl->print_footer_simple();
diff --git a/vpl.class.php b/vpl.class.php
index 548c20a26247c868dc3037f606032ce3cfd61f94..e7eff9afcf41ad485c914046cc5d1e19946e24f1 100644
--- a/vpl.class.php
+++ b/vpl.class.php
@@ -1314,6 +1314,20 @@ class mod_vpl {
         return $this->instance->grade;
     }
 
+    public function get_max_grades() {
+        global $DB;
+        if ( $this->is_group_activity() ) {
+            $field = 'groupid';
+        } else {
+            $field = 'userid';
+        }
+        $id = $this->get_instance()->id;
+        $query = "SELECT $field, max({vpl_submissions}.grade) as maxgrade FROM {vpl_submissions}";
+        $query .= " WHERE {vpl_submissions}.vpl=$id and ({vpl_submissions}.grade is not null)";
+        $query .= " GROUP BY {vpl_submissions}.$field";
+        return $DB->get_records_sql( $query );
+    }
+
     /**
      * Format given grade as grade/maxgrade
      * @param float $grade
@@ -1969,4 +1983,33 @@ class mod_vpl {
         }
         return $ret;
     }
+
+    public function count_graded() {
+        $numsubs = 0;
+        $numgraded = 0;
+        $subs = $this->all_last_user_submission( 's.dategraded, s.userid' );
+        if ($this->is_group_activity()) { // Fixes group activity userid.
+            foreach ($subs as $sub) {
+                $group = $this->get_group_members($sub->groupid);
+                if ( count($group) ) {
+                    $user = reset($group);
+                    $sub->userid = $user->id;
+                }
+            }
+        }
+        $students = $this->get_students();
+        foreach ($subs as $sub) {
+            if (isset( $students [$sub->userid] )) {
+                $numsubs ++;
+                if ($sub->dategraded > 0) { // Is graded.
+                    $numgraded ++;
+                }
+            }
+        }
+        return array (
+                'submissions' => $numsubs,
+                'graded' => $numgraded
+        );
+    }
+
 }
diff --git a/vpl_submission.class.php b/vpl_submission.class.php
index 65add2f13460c93e366c9b6940d70c4582d7e4d7..492c4a9804ecd9fc29842db6670742b71303fc1c 100644
--- a/vpl_submission.class.php
+++ b/vpl_submission.class.php
@@ -718,7 +718,7 @@ class mod_vpl_submission {
             if ($this->vpl->get_grade() != 0) {
                 $ret .= $this->vpl->str_restriction(get_string('grade'), $this->get_grade_core(), true) . '<br>';
                 if ($detailed) {
-                 $ret .= $this->reduce_grade_string() . '<br>';
+                    $ret .= $this->reduce_grade_string() . '<br>';
                     $feedback = $this->get_grade_comments();
                     if ($feedback) {
                         $div = new vpl_hide_show_div( true );
@@ -1291,4 +1291,15 @@ class mod_vpl_submission {
         }
         return $params;
     }
+
+    public function get_gradedon_date_formatted() {
+        $date = $this->instance->dategraded;
+        if ($date > 0) {
+            $gradedon = userdate( $date, get_string('strftimedatetimeshort', 'langconfig') );
+        } else {
+            $gradedon = '';
+        }
+        $fullgradedondate = userdate( $date, get_string('strftimedaydatetime', 'langconfig') );
+        return '<div value="' . $date . '" title="'.$fullgradedondate.'">'. $gradedon. '</div>';
+    }
 }